[
  {
    "path": ".gitignore",
    "content": "**/__pycache__\nenv\n/server_env\n/tmp\n/outputs\n/log\n/.idea\n/.vscode\n/.git\n/.github\ntest.bat\nserver/python_server/output/*\nserver/python_server/init_images/*\nnode_modules/\nserver/python_server/prompt_shortcut.json\nexperimental/\nstart_server.sh\nstart_server.bat\n*.ccx\n*.zip\nexpanded_mask.png\noriginal_mask.png\n/config\n\n/jimp/*\n!/jimp/browser/\n/jimp/browser/examples\n/jimp/browser/*.md\n/jimp/browser/*.editorconfig\n/jimp/browser/lib/jimp.js\n\n\n# comments when packaging (include in the package,uxp packager will use .gitignore to ignore files):\n*/dist/*LICENSE.txt\n*/dist/*.bundle.js\ntypescripts/dist\n"
  },
  {
    "path": ".prettierignore",
    "content": "server/python_server/output/*\n*.md\nmanifest.json\njimp/**\nserver_env/**\n.github\\workflows\\wiki-sync-action.yml\n**/dist\n.github\\workflows\\wiki-sync-action.yml\ntsconfig.json"
  },
  {
    "path": ".prettierrc",
    "content": "{\n    \"trailingComma\": \"es5\",\n    \"tabWidth\": 4,\n    \"semi\": false,\n    \"singleQuote\": true\n}\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2022 Abdullah Alfaraj\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "\n\n# Auto-Photoshop-StableDiffusion-Plugin\n[![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/AbdullahAlfaraj)\n[![discord badge]][discord link]\n\n[discord badge]: https://flat.badgen.net/discord/members/3mVEtrddXJ\n[discord link]: https://discord.gg/3mVEtrddXJ\n\n\n\nWith Auto-Photoshop-StableDiffusion-Plugin, you can directly use the capabilities of Automatic1111 Stable Diffusion in Photoshop without switching between programs. This allows you to easily use Stable Diffusion AI in a familiar environment. You can edit your Stable Diffusion image with all your favorite tools and save it right in Photoshop.\n\n# Table of Contents\n- [Auto-Photoshop-StableDiffusion-Plugin](#auto-photoshop-stablediffusion-plugin)\n- [Table of Contents](#table-of-contents)\n- [Demo:](#demo) \n- [Support Us On Patreon](#support-us-on-patreon)\n- [How to Install](#how-to-install)\n\t- [Method 1: One Click Installer](#method-1-one-click-installer)\n\t- [Method 2: The Unzip Method](#method-2-the-unzip-method)\n\t- [Method 3: The UXP Method (for Developers/Programmers Only)](#method-3-the-uxp-method-instruction-for-developers)\n\n- [FAQ and Known Issues](#faq-and-known-issues)\n\t- [What Photoshop version do I need to run the plugin?](#what-photoshop-version-do-i-need-to-run-the-plugin) \n\t- [Path Doesn't Exist](#path-doesnt-exist)\n\t- [Plugin Load Failed](#plugin-load-failed)\n\t\t- [No application are connected to the service](#no-application-are-connected-to-the-service)\n\t\t- [Load command failed in App with ID PS and Version X.X.X](#load-command-failed-in-app-with-id-ps-and-version-xxx)\n\t- [Exception in ASGI application / Expecting value: line 1 column 1](#exception-in-asgi-application--expecting-value-line-1-column-1)\n\t- [No Generations and Plugin Server doesn't send messages. (Remote setup)](#no-generations-and-plugin-server-doesnt-send-messages-remote-setup)\n\t\n- [No GPU Options](#no-gpu-options)\n\t- [Stable Horde](#stable-horde)\n\t- [Colab](#colab)\n\t\n# Support Us On Patreon:\nBy supporting us on [Patreon](https://www.patreon.com/AbdullahAlfaraj), you’ll help us continue to develop and improve the Auto-Photoshop-StableDiffusion-Plugin, making it even easier for you to use Stable Diffusion AI in a familiar environment. As a supporter, you’ll have the opportunity to provide feedback and suggestions for future development. Plus, you’ll get early access to new features and tutorials, as well as exclusive art tutorials and tips from a professional artist. We’re passionate about making AI approachable to artists and with your help, we can continue to do just that.\t\n# Auto-Photoshop-SD Backers and Sponsors:\n<h2>💎 Diamond</h2>\n<table>\n<tr>\n<td><a href=\"https://ronnykhalil.com/\"><img src=\"https://images.weserv.nl/?url=https://raw.githubusercontent.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/206b56c911f67ede3ca3a934d0bce8c1d68a2113/docs/profile_image/A934E4F0-7778-47E9-A395-531BFF2E61F1_1_105_c.jpeg&h=80&w=80&fit=cover&mask=circle&maxage=7d\" alt=\"Ronny Khalil\"></a></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=zachary\" alt=\"zachary\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Razvan+Matei\" alt=\"Razvan Matei\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=MasterAI\" alt=\"MasterAI\"></td>\n</tr>\n<tr>\n<td><a href=\"https://ronnykhalil.com/\">Ronny Khalil</a></td>\n<td>zachary</td>\n<td>Razvan Matei</td>\n<td>MasterAI</td>\n</tr>\n</table>\n\n<h2>🥇 Gold</h2>\n<table>\n<tr>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Alex+\" alt=\"Alex \"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Olivier+Lefebvre\" alt=\"Olivier Lefebvre\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Arthur+Liu\" alt=\"Arthur Liu\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Florin-Alexandru+Ilinescu\" alt=\"Florin-Alexandru Ilinescu\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Zenko+\" alt=\"Zenko \"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Juan+Pablo+Mendiola\" alt=\"Juan Pablo Mendiola\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Robin+Edwards\" alt=\"Robin Edwards\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Frederic+Dreuilhe\" alt=\"Frederic Dreuilhe\"></td>\n</tr>\n<tr>\n<td>Alex </td>\n<td>Olivier Lefebvre</td>\n<td>Arthur Liu</td>\n<td>Florin-Alexandru Ilinescu</td>\n<td>Zenko </td>\n<td>Juan Pablo Mendiola</td>\n<td>Robin Edwards</td>\n<td>Frederic Dreuilhe</td>\n</tr>\n<tr>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Danny+Sahagun\" alt=\"Danny Sahagun\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=darius+coal\" alt=\"darius coal\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Kerwin\" alt=\"Kerwin\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=The+Dread+Vixen+Alinsa\" alt=\"The Dread Vixen Alinsa\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Bruce+Hunter\" alt=\"Bruce Hunter\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Chris+Canterbury\" alt=\"Chris Canterbury\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Lawrence+L+Tran\" alt=\"Lawrence L Tran\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Jake+Skokan\" alt=\"Jake Skokan\"></td>\n</tr>\n<tr>\n<td>Danny Sahagun</td>\n<td>darius coal</td>\n<td>Kerwin</td>\n<td>The Dread Vixen Alinsa</td>\n<td>Bruce Hunter</td>\n<td>Chris Canterbury</td>\n<td>Lawrence L Tran</td>\n<td>Jake Skokan</td>\n</tr>\n<tr>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=que0005\" alt=\"que0005\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Xavier+Matia+Bernasconi\" alt=\"Xavier Matia Bernasconi\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Mats+Oldin\" alt=\"Mats Oldin\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Rodrigo+Terra\" alt=\"Rodrigo Terra\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Nicolas+Meunier\" alt=\"Nicolas Meunier\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Ihor+Pankin\" alt=\"Ihor Pankin\"></td>\n</tr>\n<tr>\n<td>que0005</td>\n<td>Xavier Matia Bernasconi</td>\n<td>Mats Oldin</td>\n<td>Rodrigo Terra</td>\n<td>Nicolas Meunier</td>\n<td>Ihor Pankin</td>\n</tr>\n</table>\n\n<h2>🥈 Silver</h2>\n<table>\n<tr>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Amith+Thomas\" alt=\"Amith Thomas\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=xiao+yuan\" alt=\"xiao yuan\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Ezra+Blake\" alt=\"Ezra Blake\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Kevin+Schofield\" alt=\"Kevin Schofield\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Mvs+Srs\" alt=\"Mvs Srs\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Felipe+Cortes\" alt=\"Felipe Cortes\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Smith\" alt=\"Smith\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Sanchez\" alt=\"Sanchez\"></td>\n</tr>\n<tr>\n<td>Amith Thomas</td>\n<td>xiao yuan</td>\n<td>Ezra Blake</td>\n<td>Kevin Schofield</td>\n<td>Mvs Srs</td>\n<td>Felipe Cortes</td>\n<td>Smith</td>\n<td>Sanchez</td>\n</tr>\n<tr>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Ziui+Witter\" alt=\"Ziui Witter\"></td>\n</tr>\n<tr>\n<td>Ziui Witter</td>\n</tr>\n</table>\n\n<h2>🥉 Copper</h2>\n<table>\n<tr>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Sebastian+Karbowniczek\" alt=\"Sebastian Karbowniczek\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Petter+Lundh\" alt=\"Petter Lundh\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=AWWalker\" alt=\"AWWalker\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=cdmusic\" alt=\"cdmusic\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=Jason+Bessonette\" alt=\"Jason Bessonette\"></td>\n<td><img src=\"https://ui-avatars.com/api/?background=random&color=fff&rounded=true&name=22two+\" alt=\"22two \"></td>\n</tr>\n<tr>\n<td>Sebastian Karbowniczek</td>\n<td>Petter Lundh</td>\n<td>AWWalker</td>\n<td>cdmusic</td>\n<td>Jason Bessonette</td>\n<td>22two </td>\n</tr>\n</table>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<a href=\"https://www.patreon.com/AbdullahAlfaraj\" rel=\"nofollow\"><img src=\"docs/become_backer.svg\" style=\"max-width: 100%;\"></a>\n\n\n# How To Install: \nUse method 1 or 2 if you are an Artist\nuse method 3 if you are a Developer/Programmer \n\n\n# Method 1: One Click Installer\n\n1) Download the [.ccx](https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/releases/latest) file\n2) run the ccx file . that's all.  you will be able to use all of stable diffusion modes (txt2img, img2img, inpainting and outpainting), check the [tutorials](https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/wiki) section to master the tool. \n\n![install_plugin_1](https://user-images.githubusercontent.com/7842232/217213943-3e2a588d-3ed8-4757-ba69-9846b55a1b36.gif)\n\n\n3) (Don't skip) Install the `Auto-Photoshop-SD` Extension from Automatic1111 extension tab. The extension will allow you to use mask expansion and mask blur, which are necessary for achieving good results when outpainting and inpainting.\n - a) Copy Auto-Photoshop plugin url\n![copy_githup_url_2](https://user-images.githubusercontent.com/7842232/217213998-367873ce-2c09-4c42-a5fa-0044415e3908.gif)\n\n- b) Paste the url in auto1111's extension tab and click install\n\n![install_extension_3](https://user-images.githubusercontent.com/7842232/217214062-4c2fef9e-8d49-46a0-aa3b-80c4975f8a70.gif)\n\n- c) Make sure the Auto-Photoshop plugin is listed, then click \"Apply and Restart UI\"\n\n![apply_and_restart_4](https://user-images.githubusercontent.com/7842232/217214116-2e30d7b8-aeb6-44df-aff3-4788a56cd800.gif)\n\n\n\n# Method 2: The Unzip Method\n1) Download the  [.zip](https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/releases/latest) file\n2) Unzip it in a folder with the same name\n3) move the unzipped folder to the Photoshop Plugin folder\n4) (Don't skip) Install the `Auto-Photoshop-SD` Extension from Automatic1111 extension tab. The extension will allow you to use mask expansion and mask blur, which are necessary for achieving good results when outpainting and inpainting.\n - a) Copy Auto-Photoshop plugin url\n![image](https://user-images.githubusercontent.com/7842232/223751539-1a3013aa-aa1d-4058-87ae-e8b3fdfc5ec8.png)\n\n\n\n# Method 3: The UXP method (Instruction for Developers):\nFor artists we recommend you use [the one click installer](#one-click-installer). If you are a developer Watch the any of these videos or follow the instruction bellow. \n\n<a href=\"https://www.youtube.com/watch?v=BNzdhEpFHrg&ab_channel=Abdsart\" title=\"How To Install Auto Photoshop Stable Diffusion Plugin by Abdullah Alfaraj\" rel=\"Click Here to Watch How To Install Tutorial by Abdullah Alfaraj\"><img src=\"https://user-images.githubusercontent.com/7842232/217941315-8d4a3b25-1a83-4dac-b921-79b3f82e0536.png\" style=\"width:500px\"></a>\n\n<a href=\"https://www.youtube.com/watch?v=CJuTZw39Reg&t=145s&ab_channel=VladimirChopine%5BGeekatPlay%5D\" title=\"How To Install Auto Photoshop Stable Diffusion Plugin by Vladimir Chopine\" rel=\"Click Here to Watch How To Install Tutorial by Vladimir Chopine\"><img src=\"https://i3.ytimg.com/vi/CJuTZw39Reg/maxresdefault.jpg\" style=\"width:500px\"></a>\n\nFor artists we recommend you use [the one click installer](#one-click-installer)\n## First time running the plugin (local Automatic1111):\n1) download the plugin:\n```\ngit clone https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin.git\n```\n2) open cmd window in the \"Auto-Photoshop-StableDiffusion-Plugin\" directory and then install the dependencies by typing:\n```\nnpm install\n```\n3) build the plugin by transpiling typescript to javascript:\n```\nnpm run watch\n```\n\n4) run \"start_server.bat\" inside \"Auto-Photoshop-StableDiffusion-Plugin\" directory\n5) go to where you have [automatic1111](https://github.com/AUTOMATIC1111/stable-diffusion-webui) installed. \nEdit the \"webui-user.bat\" in automatic1111 \n change this line \n```\nset COMMANDLINE_ARGS= \n```\nto\n```\nset COMMANDLINE_ARGS= --api\n```\nthat will allow the plugin to communicate with the automatic1111 project. After saving close the \"webui-user.bat\" file and run it normally.\n\n6) run photoshop. go to edit -> prefrences -> plugins\n\t1) make sure you check \"Enable Developer Mode\" checkbox\n7) install \"Adobe UXP Developer Tool\" from here [Installation (adobe.com)](https://developer.adobe.com/photoshop/uxp/devtool/installation/)\n   this tool will add the plugin into photoshop\n8) run Adobe UXP Developer Tool and click on \"Add Plugin\" button in the top right. Navigate to where you have \"Auto-Photoshop-StableDiffusion-Plugin\" folder and open \"manifest.json\"\n9) select the plugin and click on Actions -> Load Selected\nthat's it.\n\n## First time running the plugin (remote Automatic1111):\n__The remote webui must also have `--api` set in `COMMANDLINE_ARGS`. You can check if api access is enabled by appending \"/docs#\" to the end of the url. If the documentation includes `/sdapi/v1/samplers` then api access is enabled.__\n\n1) download the plugin:\n```\ngit clone https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin.git\n```\n1) edit [start_server.bat](start_server.bat) (or start_server.sh if on linux) to point to the remote installation of Automatic1111\n2) run \"start_server.bat\" inside \"Auto-Photoshop-StableDiffusion-Plugin\" directory\n3) run photoshop. go to edit -> prefrences -> plugins\n\t1) make sure you check \"Enable Developer Mode\" checkbox\n4) install \"Adobe UXP Developer Tool\" from here [Installation (adobe.com)](https://developer.adobe.com/photoshop/uxp/devtool/installation/)\n   this tool will add the plugin into photoshop\n5) run Adobe UXP Developer Tool and click on \"Add Plugin\" button in the top right. Navigate to where you have \"Auto-Photoshop-StableDiffusion-Plugin\" folder and open \"manifest.json\"\n6) select the plugin and click on Actions -> Load Selected\nthat's it.\n\n\n\n\n\n\n# Demo:\n[![Click Here to Watch Demo](https://i3.ytimg.com/vi/VL_gbQai79E/maxresdefault.jpg)](https://youtu.be/VL_gbQai79E \"Stable diffusion AI Photoshop Plugin Free and Open Source\")\n\n\n# FAQ and Known Issues\n## What Photoshop version do I need to run the plugin?\nThe minimum Photoshop version that the plugin supports is Photoshop v24\n\n## Plugin Load Failed\nThere are a few issues that can result in this error, please follow the instructions for the corresponding error message in the UDT logs\n\n### No application are connected to the service\nThis error occurs when Photoshop is not started before the plugin is attempted to be loaded. Simply start photoshop then restart UXP and load the plugin\n\n\n## Exception in ASGI application / Expecting value: line 1 column 1\nThis error occurs due to mismatched expectations between the plugin and the Automatic1111 backend. \nIt can be solved by both updating the version of the Automatic111 backend to the latest verion, and making sure \"Save text information about generation parameters as chunks to png files\" setting is enabled within the UI.\n\n## No Generations and Plugin Server doesn't send messages. (Remote setup)\nThis error occurs when the remote server does not have the api enabled. You can verify this by attempting to go to the URL you access the webui at and appending \"/docs#\" to the end of the url. If you have permissions, make relaunch the remote instance with the \"--api\" flag. \n\n# No GPU Options:\nwe provide two options to use the auto-photoshp plugin without GPU.\n## Stable Horde\nThis is an awesome free crowdsourced distributed cluster of Stable Diffusion workers. If you like this service, consider joining the horde yourself!\nthe horde is enabled completely by the generosity of volunteers so make sure you don't overwhelm the service and help join the cause if you can.\nread more on their [GitHub page](https://github.com/db0/AI-Horde)\n## Colab:\nwe link to this [Colab](https://colab.research.google.com/drive/1nbcx_WOneRmYv9idBO33pN5CbxXrqZHu?usp=sharing#scrollTo=Y4ebYsPqTrGb) directly inside plugin find it in the settings tab. you only need to run it. no need to change any of the settings. copy the gradio.live url the colab will generate and paste it into ```sd url``` field in the settings tab.\n"
  },
  {
    "path": "build-script/pack-ccx.mjs",
    "content": "import chalk from 'chalk'\nimport { program } from 'commander'\nimport { createWriteStream, readFileSync, statSync, writeFileSync } from 'fs'\nimport { globSync } from 'glob'\nimport { dirname, join, relative } from 'path'\nimport { fileURLToPath } from 'url'\nimport yazl from 'yazl'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst basePath = join(__dirname, '..')\n\nprogram.requiredOption('--version <platform>', 'the target platform').parse()\n\nconst version = program.opts().version\nif (!version.match(/\\d+\\.\\d+\\.\\d+/))\n    throw new Error(`invalid version format: ${version}`)\n\nconsole.log(chalk.cyan(\"rewriting manifest.json's version field to \" + version))\nconst manifest = JSON.parse(readFileSync(`${basePath}/manifest.json`, 'utf-8'))\nmanifest.version = version\nwriteFileSync(`${basePath}/manifest.json`, JSON.stringify(manifest))\n\nconsole.log(chalk.cyan(\"rewriting package.json's version field to \" + version))\nconst packageJSON = JSON.parse(\n    readFileSync(`${basePath}/package.json`, 'utf-8')\n)\npackageJSON.version = version\nwriteFileSync(`${basePath}/package.json`, JSON.stringify(packageJSON))\n\nconsole.log(chalk.cyan('packaging .ccx'))\nconst zipList = [\n    './manifest.json',\n    './i18n/**/*',\n    './icon/**/*',\n    './jimp/**/*',\n    './scripts/**/*',\n    './typescripts/dist/**/*',\n    './utility/**/*',\n    './server/**/*',\n    './*.js',\n    './package.json',\n    './tsconfig.json',\n    './*.html',\n    './*.py',\n    './*.txt',\n    './*.md',\n    './*.png',\n    './presets/**/*',\n    './typescripts/comfyui/**/*.json',\n]\n\nconst zipfile = new yazl.ZipFile()\n\nzipList.forEach((globber) => {\n    globSync(join(basePath, globber).replace(/\\\\/g, '/')).forEach(\n        (filepath) => {\n            if (statSync(filepath).isDirectory()) return\n\n            const rpath = relative(basePath, filepath)\n            zipfile.addFile(filepath, rpath)\n        }\n    )\n})\n\nzipfile.outputStream.pipe(\n    createWriteStream(\n        join(basePath, `Auto.Photoshop.SD.plugin_v${version}.ccx`)\n    )\n)\nzipfile.outputStream.pipe(\n    createWriteStream(\n        join(basePath, `Auto.Photoshop.SD.plugin_v${version}.zip`)\n    )\n)\n\nzipfile.end()\n"
  },
  {
    "path": "build-script/webpack.config.js",
    "content": "const path = require('path')\n// const CleanWebpackPlugin = require('clean-webpack-plugin')\nconst CopyPlugin = require('copy-webpack-plugin')\n\nmodule.exports = {\n    entry: {\n        bundle: path.resolve(__dirname, '../typescripts/entry.ts'),\n    },\n    output: {\n        path: path.resolve(__dirname, '../typescripts/dist'),\n        filename: '[name].js',\n        libraryTarget: 'commonjs2',\n    },\n    mode: 'development',\n    // mode: 'production',\n\n    devtool: false,\n\n    externals: {\n        uxp: 'commonjs2 uxp',\n        photoshop: 'commonjs2 photoshop',\n        os: 'commonjs2 os',\n        fs: 'commonjs2 fs',\n    },\n    resolve: {\n        extensions: ['.tsx', '.ts', '.js', '.jsx'],\n\n        fallback: {\n            util: require.resolve('util/'),\n        },\n    },\n    module: {\n        rules: [\n            {\n                test: /\\.tsx?$/,\n                loader: 'ts-loader',\n                exclude: /node_modules/,\n                options: {\n                    configFile: path.resolve(__dirname, '../typescripts/tsconfig.json'),\n                },\n            },\n            {\n                test: /\\.jsx?$/,\n                exclude: /node_modules/,\n                loader: 'babel-loader',\n                options: {\n                    plugins: [\n                        '@babel/transform-react-jsx',\n                        '@babel/proposal-object-rest-spread',\n                        '@babel/plugin-syntax-class-properties',\n                    ],\n                },\n            },\n            {\n                test: /\\.png$/,\n                exclude: /node_modules/,\n                loader: 'file-loader',\n            },\n            {\n                test: /\\.css$/,\n                use: ['style-loader', 'css-loader'],\n            },\n            {\n                test: /\\.svg$/,\n                use: ['@svgr/webpack', 'url-loader'],\n            },\n        ],\n    },\n    plugins: [\n        //new CleanWebpackPlugin(),\n        // new CopyPlugin(['plugin'], {\n        //     copyUnmodified: true,\n        // }),\n    ],\n}\n"
  },
  {
    "path": "deprecated-do-not-use-start_server.bat",
    "content": "@REM @echo off\ngit pull\n\nset SD_URL=http://127.0.0.1:7860\n\necho does server_env\\ exist\nif exist server_env\\ (\n  echo Yes \n  goto :activate_server_env\n) else (\n  echo No\n  goto :create_server_env\n)\n\n:create_server_env\npython -m venv server_env\n\n\n\n\n@REM pause\n\n\n:activate_server_env\n\n::run a server\necho my_path: %~dp0\n@REM set current_dir=\nset VENV_DIR=%~dp0server_env\n@REM cd ./server_env/Scripts/\nset PYTHON=\"%VENV_DIR%\\Scripts\\Python.exe\"\n%PYTHON% -m pip install -r requirements.txt\n\ncd ./server/python_server\necho python path: %PYTHON%\ndir\necho %PYTHON% uvicorn serverMain:app --reload\n%PYTHON% -m uvicorn serverMain:app --reload\npause\n@REM exit /b\n@REM %PYTHON% uvicorn serverMain:app --reload\npause\n\n@REM %PYTHON% img2imgapi.py\n@REM activate\n@REM echo server_env %PYTHON%\n@REM cd ./server/python_server\n@REM %PYTHON% img2imgapi.py\n@REM uvicorn serverMain:app --reload\n@REM dir .\n@REM call webui.bat\n"
  },
  {
    "path": "deprecated-do-not-use-start_server.sh",
    "content": "#!/bin/bash\ngit pull\n# Set the desired remote host where the \"<>\" is\nexport SD_URL=http://127.0.0.1:7860\n\n# Check python was installed\nif ! hash python; then\n    echo \"Python is not installed\"\n    exit 1\nfi\n\n# Check the default python version\norig_ver=$(python -V 2>&1)\nmajor_version=$(echo \"$orig_ver\" | sed 's/[^0-9]*\\([0-9]*\\)\\..*/\\1/')\nminor_subversion=$(echo \"$orig_ver\" | sed -E 's/^[^.]*\\.([^.]*).*$/\\1/')\nif [[ \"$major_version\" -ge \"3\" ]] && [[ \"$minor_subversion\" -ge \"7\" ]] # Because of uvicorn==0.20.0 in requirements\nthen\n    echo \"You have valid version of $orig_ver\"\nelse\n    echo \"Your version $orig_ver not valid, should be >=3.7\"\n    exit 1\nfi\n\n\n# Check if the desired environment exists\nif [ ! -d \"server_env\" ]; then\n  # Create the environment if it doesn't exist\n  python -m venv server_env\n  source ./server_env/bin/activate\n  python -m pip install -r requirements.txt\nelse\n  source ./server_env/bin/activate\nfi\n\ncd ./server/python_server\npython -m uvicorn serverMain:app --reload\n"
  },
  {
    "path": "deprecated-do-not-use-start_server_MacOS.sh",
    "content": "#!/bin/bash\ngit pull\n# Set the desired remote host where the \"<>\" is\nexport SD_URL=http://127.0.0.1:7860\n\n# Check if the desired environment exists\nif [ ! -d \"server_env\" ]; then\n  # Create the environment if it doesn't exist\n  python3 -m venv server_env\n  source ./server_env/bin/activate\n  python3 -m pip install -r requirements.txt\nelse\n  source ./server_env/bin/activate\nfi\n\ncd ./server/python_server\npython3 -m uvicorn serverMain:app --reload\n"
  },
  {
    "path": "deprecated-do-not-use-update_plugin.bat",
    "content": "git pull"
  },
  {
    "path": "deprecated-do-not-use-update_plugin.sh",
    "content": "#!/bin/bash\ngit pull"
  },
  {
    "path": "dialog_box.js",
    "content": "async function prompt(\n    heading,\n    body,\n    buttons = ['Cancel', 'Ok'],\n    options = { title: heading, size: { width: 360, height: 280 } }\n) {\n    const [dlgEl, formEl, headingEl, dividerEl, bodyEl, footerEl] = [\n        'dialog',\n        'form',\n        'sp-heading',\n        'sp-divider',\n        'sp-body',\n        'footer',\n    ].map((tag) => document.createElement(tag))\n    ;[headingEl, dividerEl, bodyEl, footerEl].forEach((el) => {\n        el.style.margin = '6px'\n        el.style.width = 'calc(100% - 12px)'\n    })\n\n    formEl.setAttribute('method', 'dialog')\n    formEl.addEventListener('submit', () => dlgEl.close())\n\n    footerEl.style.marginTop = '26px'\n\n    dividerEl.setAttribute('size', 'large')\n\n    headingEl.textContent = heading\n\n    bodyEl.textContent = body\n\n    buttons.forEach((btnText, idx) => {\n        const btnEl = document.createElement('sp-button')\n        btnEl.setAttribute(\n            'variant',\n            idx === buttons.length - 1 ? btnText.variant || 'cta' : 'secondary'\n        )\n        if (idx === buttons.length - 1)\n            btnEl.setAttribute('autofocus', 'autofocus')\n        if (idx < buttons.length - 1) btnEl.setAttribute('quiet')\n        btnEl.textContent = btnText.text || btnText\n        btnEl.style.marginLeft = '12px'\n        btnEl.addEventListener('click', () =>\n            dlgEl.close(btnText.text || btnText)\n        )\n        footerEl.appendChild(btnEl)\n    })\n    ;[headingEl, dividerEl, bodyEl, footerEl].forEach((el) =>\n        formEl.appendChild(el)\n    )\n    dlgEl.appendChild(formEl)\n    document.body.appendChild(dlgEl)\n\n    return dlgEl.uxpShowModal(options)\n}\n\n// const r1 = await prompt(\n//   'Upload Large File',\n//   'This is a large file (over 100MB) -- it may take a few moments to upload.',\n//   ['Skip', 'Upload']\n// )\n// if ((r1 || 'Upload') !== 'Upload') {\n//   /* cancelled or No */\n// } else {\n//   /* Yes */\n// }\n\n// const r2 = await prompt(\n//   'Delete File',\n//   'Are you sure you wish to delete this file? This action cannot be undone.',\n//   ['Cancel', { variant: 'warning', text: 'Delete' }]\n// )\n// if (r2 !== 'Delete') {\n//   /* nope, don't do it! */\n// } else {\n//   /* Do the delete */\n// }\n\nmodule.exports = { prompt }\n"
  },
  {
    "path": "docs/Home.md",
    "content": "\n*Version 1.1.0*\n\n## Introduction\n\nThis guide explains the Auto Photoshop UI and its main features, it doesn't go into any detail of how Stable Diffusion works or the functionalities implemented by AUTOMATIC1111. For the latter you can read the manual [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features).\n\n## Stable Diffusion UI Tab\n\n![[Pasted image 20230131191554.png]]\n\n- **Model Selection** - allows to select the .ckpt / .safetensors model to be used for image generation.\n- **Refresh** - refreshes the models. *Note*: this will extract all loaded models in AUTOMATIC1111, if you want to add a new model, first refresh AUTOMATIC1111.\n- **L2S (Layer to selection)** - convenience function to move the content of the currently selected layer into the photoshop selection.\n- **Snapshot** - convenience function equivalent to \"ALT + Merge Visible Layers\"\n- **Reset** - reset UI to default values\n- **Prompt Shortcut** - enables prompt shortcuts\n- Prompt - text area for the image generation prompt\n- Negative Prompt - text area for the image generation negative prompt\n\n### txt2img\n\n[[Pasted image 20230131192430.png]]\n\n- **Images**: number of images to be generated in a single generation session\n- **Steps**: number of steps\n- **Selection Mode Ratio**: the generation dimension will be set automatically to match the proportion of the photoshop selection, using 512 as the base value.\n- **Selection Mode Precise**: the generation dimension will be set to match exactly the photoshop selection.\n- **Selection Mode Ignore**: the generation dimension are set by the user.\n- **Width and Heigth**: the image generation dimensions\n- **CFG Scale**: Influence strength of the prompt (for details please see the  AUTOMATIC1111 wiki)\n- **Restore Faces**: enables the restore faces function in AUTOMATIC1111\n- **Hi Res Fix**: enables the Hi Res Fix function in AUTOMATIC1111 (see below)\n- **Seed**: Displays and edit current seed (-1 = Random)\n- **Random / Last**: sets seed to either random or last generation\n- **Show Samplers**: allows to select the sampler used for image generation\n\n**Hi Res Fix**\n\n[[Pasted image 20230131195947.png]]\n\nWhen Hi Res is checked, a number of parameters become avaiable including Upscaler model to be used, output dimensions and denoising strength. This is just an interface into the AUTOMATIC1111 functionality described [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#hires-fix).\n\n### img2img\n\n[[Pasted image 20230131200253.png]]\n\n- **Image**: shows the current image used as img2img base.\n- **Denoising Strength**: how much Stable Diffusion should be influenced by the image, 0 = output is same as image, 1 = completely different image.\n- **Inpainting conditioning mask strength**; this field only works with inpainting special models (ending in \"-inpainting.\"). Determines how much the process should stick to the image structure, check out [this post](https://www.reddit.com/r/StableDiffusion/comments/yi46px/new_hidden_img2img_feature_conditioning_mask/) for details.\n\n### inpaint\n\n[[Pasted image 20230131201122.png]]\n\n- **Image / Mask**: show image and mask used for the inpaint process\n- **Denoising Strength**: similar to img2img however it behaves differently depending on Mask Content context.\n- **Mask Blur**: how much to blur the mask before processing it in pixels\n- **Mask Expansion**: how much the mask should expand to create a more blended output image\n- Mask Content Fill: fill it with colors of the image\n- Mask Content original: keep whatever was there originally\n- Mask Content latent noise: fill it with latent space noise\n- Mask Content latent nothing: fill it with latent space zeros\n- **Inpaining at Full Res**: have a look [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/4637) for an explanation of this feature.\n- **Restore Faces**: same as img2img\n\n### outpaint\n\nUI and its functionality are same as inpaint.\n\n\n\n\n\n\n\n## Viewer\n\nTab to manage the images generated in the current session.\n\n[[Pasted image 20230131202255.png]]\n\n- Set Mask: manually sets the currently selected mask\n- Set Init Image: manually sets the currently selected image\n- Generate More: adds more generated images to the current session\n- Selection Area: selects the boundaries of the currently selected image in the viewer\n- [[Pasted image 20230131202517.png]] Keep all images generated in the current session\n- [[Pasted image 20230131202539.png]] Discard all images generated in the current session\n- [[Pasted image 20230131202558.png]] Keep only the selected image in the viewer\n- [[Pasted image 20230131202638.png]] Discard the selected image in the viewer\n\n## History\n\n[[Pasted image 20230201161508.png]]\n\n- **Load Previous Generations**: loads the images generated within this Photoshop file.\n- [[Pasted image 20230201161716.png]] hovering on the image loaded from history will allow bringing the image back into the Photoshop Layer stack\n- Clicking on the image will load the pluging settings for the image generation (seed and image generation configuration)\n- **Image Search**: loads a set of images from the internet, clicking on any of the images will load them into the layer stack.\n\n## Prompts Library\n\n[[Pasted image 20230201161938.png]]\n\n- For this to work a file will need to be created in the following location: Auto-Photoshop-StableDiffusion-Plugin\\\\server\\\\python_server\\\\prompt_shortcut.json\n- **Load / Save**: Once the file is present, values can be loaded and saved onto the file.\n- **Key / Value / Add top Prompt Shortcut**: allows to change / add values to the existing json file.\n- **Refresh Menu**: will load all values from the json, allowing the user to make changes to the value.\n\n## Horde\n\nComing Soon\n\n## Settings \n\n[[Pasted image 20230201163236.png]]\n\n# Tutorials\n\n## Generate a txt2img\n\n[[Generate txt2img.gif]]\n\n1. Make a selection where you want the image to be generated\n2. Press [[Pasted image 20230203191656.png]]\n3. (optional) use the Viewer to select which images to keep in case of multiple image generation\n\n## Using the Viewer\n\n[[Viewer Tutorial.gif]]\n1. Generate images as usual\n2. Select the image in the viewer grid (shift + click for multiple selection)\n3. Choose from: keep one, discard one, keep all, discard all.\n4. Images are saved in the latest session layer folder.\n\n## History Tab\n\n[[History.gif]]\n\n1. Load Previous Generations button\n2. Single click on image to load its settings in the Stable Diffusion tab (seed, prompt, etc)\n3. Click on edit button to load the image in Photoshop\n\n## Generate an img2img\n\n[[img2img.gif]]\n\n1. Select the portion of the image to be used as a sample\n2. Select img2img mode and adjust the parameters (denoising strenght especially)\n3. Press Generate img2img\n4. (optional) use the Viewer to select which images to keep in case of multiple image generation\n\n## Prompts Shortcut\nyou can substitute a whole sequence of words with one word. \n\nInstead of writing the following as a prompt :\n```\nUnreal Engine, Octane Render, arcane card game ui, hearthstone art style, epic fantasy style art\n```\nyou could write: \n```\n{game_like}\n```\n\nas long as you have defined the relationship in the prompt library tab\n```\n{\n\"game_like\": \"Unreal Engine, Octane Render, arcane card game ui, hearthstone art style, epic fantasy style art\"\n}\n```\n\n\n[[prompt_shortcut_file.gif]]\n\n\n### Editing and Using a Prompt File\n[[prompt_shortcut.gif]]\n\n1. Switch to the *Prompt Shortcut* tab.\n2. Load the json file.\n3. Input a keyword and its value\n4. Press *Add to Prompt Shortcut*\n5. Now the new Prompt Shortcut can be used in the Stable Diffusion tab\n6. To reuse previously saved shortcuts, ensure you load the json file at the start of each session.\n\n## Inpainting\n\n[[inpainting.gif]]\n\n1. Select inpainting mode in the Stable Diffusion tab\n2. Select the target area where to produce the image using rectangular marquee tool\n3. With a 100% opacity white brush paint the area that you wish to inpaint\n4. Ensure that you have a -inpainting.ckpt model selected (this is as important as it is easy to forget)\n5. Write a prompt describing the inpaining image\n6. Select the desired Mask Content option and adjust the Denoising Strength accordingly.\n7. Hit Generate\n\n## Outpainting\n\n[[outpainting.gif]]\n\n1. Select outpainting mode in the Stable Diffusion tab\n2. Select the target area where to produce the image using rectangular marquee tool, ensure that you have **some overlap** with the existing image (to provide Stable Diffusion with some context) and that the target area is **transparent**.\n4. Ensure that you have a -inpainting.ckpt model selected (this also works for outpainting)\n5. Write a prompt describing the outpaining image\n6. Select the desired Mask Content option and adjust the Denoising Strength accordingly.\n7. Hit Generate\n\n\n## Heal Brush\n[[heal_brush.gif]]\n1. Select the \"Heal Brush\" from the Smart Preset dropdown menu in the Stable Diffusion tab\n2. Select the target area where to produce the image using rectangular marquee tool\n3. With a 100% opacity white brush paint the area that you wish to erase\n4. Ensure that you have a -inpainting.ckpt model selected (this is as important as it is easy to forget)\n5. Write a prompt describing what you would like to see in the erased area\n6. Hit Generate"
  },
  {
    "path": "enum.js",
    "content": "const clickTypeEnum = {\n    Click: 'click',\n    ShiftClick: 'shift_click',\n    AltClick: 'alt_click',\n    SecondClick: 'second_click', //when we click a thumbnail that is active/ has orange border\n}\nconst generationModeEnum = {\n    Txt2Img: 'txt2img',\n    Img2Img: 'img2img',\n    Inpaint: 'inpaint',\n    Outpaint: 'outpaint',\n    Upscale: 'upscale',\n}\n\nconst AutomaticStatusEnum = {\n    NoApi: 'no_api',\n    Offline: 'offline',\n    RunningNoApi: 'running_no_api',\n    RunningWithApi: 'running_with_api',\n    AutoPhotoshopSDExtensionMissing: 'auto_photoshop_sd_missing',\n}\n\nconst ViewerObjectTypeEnum = {\n    OutputImage: 'output_image',\n    InitImage: 'init_image',\n    MaskImage: 'mask_image',\n}\n\nconst RequestStateEnum = {\n    Generating: 'generating', // in the generation process\n    Interrupted: 'interrupted', // canceled/ interrupted\n    Finished: 'finished', // finished generating\n}\n\nconst BackgroundHistoryEnum = {\n    CorrectBackground: 'correct_background',\n    NoBackground: 'no_background',\n}\n\nmodule.exports = {\n    clickTypeEnum,\n    generationModeEnum,\n    AutomaticStatusEnum,\n    ViewerObjectTypeEnum,\n    RequestStateEnum,\n\n    BackgroundHistoryEnum,\n}\n"
  },
  {
    "path": "helper.js",
    "content": "const { unselectActiveLayers } = require('./psapi')\n\nconst app = window.require('photoshop').app\n\nfunction getActiveLayer() {\n    let activeLayers = app.activeDocument.activeLayers\n    // console.dir(getSize())\n    for (const layer of activeLayers) {\n        console.dir({ layer })\n        const name = layer.name\n        console.dir({ name })\n        let layer_size = getLayerSize(layer)\n        console.dir({ layer_size })\n    }\n\n    return activeLayers[0]\n}\n\nfunction getSize() {\n    let doc = app.activeDocument\n    return { height: doc.height, width: doc.width }\n}\n\nconst { batchPlay } = require('photoshop').action\nconst { executeAsModal } = require('photoshop').core\n\nasync function reselectBatchPlay(selectionInfo) {\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _obj: 'rectangle',\n                    top: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.top,\n                    },\n                    left: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.left,\n                    },\n                    bottom: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.bottom,\n                    },\n                    right: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.right,\n                    },\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n}\n\nasync function reselect(selectionInfo) {\n    await executeAsModal(\n        async () => {\n            reselectBatchPlay(selectionInfo)\n        },\n        { commandName: 'reselect' }\n    )\n}\n\n//unselect the rectangular marquee selection area\nasync function unSelect() {\n    const batchPlay = require('photoshop').action.batchPlay\n\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _enum: 'ordinal',\n                    _value: 'none',\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n\n    return result\n}\n\n/**\n * Convert 1d index to 2d array\n * @param {number} index sequential index\n * @param {number} width width of 2d array\n * @returns {number[]} [x,y]\n */\nfunction indexToXY(index, width) {\n    return [index % width, Math.floor(index / width)]\n}\n\nmodule.exports = {}\n"
  },
  {
    "path": "i18n/zh_CN/ps-plugin.json",
    "content": "{\n    \"Auto-Photoshop-SD\": \"SD插件（明空汉化）\",\n    \"'A' for Automatic1111 server (webui-user.bat), Green is connected. Red Means there is a problem with your Automatic1111. Run 'webui-user.bat' and hit 'Refresh' button \": \"A代表SD服务器(webui-user.bat)，绿色已连接。红色表示SD服务器有问题。运行“webui-user.bat”并点击刷新按钮\",\n    \"'P' for proxy server (start_server.bat), Green is connected. Red means you need to run 'start_server.bat' or hit Refresh button\": \"P为代理服务器(start_server.bat)，绿色已连接。红色表示您需要运行'start_server.bat'或点击刷新按钮\",\n    \"Stable Diffusion\": \"稳定扩散\",\n    \"Stable Diffusion UI\": \"稳定扩散 UI\",\n    \"Refresh\": \"刷新\",\n    \"Refresh the plugin, only fixes minor issues.\": \"刷新插件，仅修复小问题。\",\n    \"Update\": \"更新\",\n    \"Update the plugin if you encounter bugs. Get the latest features\": \"如果遇到错误，请更新插件。 获取最新功能\",\n    \"Select Lora\": \"选择 Lora\",\n    \"use lora in your prompt\": \"在提示中使用 lora\",\n    \"Generate\": \"生成\",\n    \"Generate Txt2Img\": \"生成 Txt2Img\",\n    \"Generate Img2Img\": \"生成 Img2Img\",\n    \"Generate Inpaint\": \"生成 Inpaint\",\n    \"Generate Outpaint\": \"生成 Outpaint\",\n    \"outpaint\": \"outpaint\",\n    \"Progress...\": \"进度...\",\n    \"Toggle the visibility of the Preview Image on the canvas\": \"切换画布上预览图像的可见性\",\n    \"Move and reSize the highlighted layer to fit into the Selection Area\": \"移动和调整突出显示的图层以适合选择区域\",\n    \"create a snapshot of what you see on the canvas and place on a new layer\": \"创建画布上看到的快照并放置在新图层上\",\n    \"reset the ui settings to their default values\": \"将 UI 设置重置为默认值\",\n    \"Interrogate the selected area, convert Image to Prompt\": \"审问所选区域，将图像转换为提示\",\n    \"use this mode to generate images from text only\": \"使用此模式仅从文本生成图像\",\n    \"use this mode to generate variation of an image\": \"使用此模式生成图像的变体\",\n    \"use this mode to generate variation of a small area of an image, while keeping the rest of the image intact\": \"使用此模式生成图像的小区域的变体，同时保持图像的其余部分完好无损\",\n    \"use this mode to (1) fill any missing area of an image,(2) expand an image\": \"使用此模式来（1）填充图像的任何缺失区域，（2）扩展图像\",\n    \"Image\": \"图像\",\n    \"Mask\": \"蒙版\",\n    \"Batch Size:\": \"批量大小：\",\n    \"Batch Count:\": \"批量计数：\",\n    \"Steps:\": \"步数：\",\n    \"Selection Mode:\": \"选择模式：\",\n    \"ratio\": \"比率\",\n    \"precise\": \"精确\",\n    \"use the selection area width and height to fill the width and height sliders\": \"使用选择区域的宽度和高度来填充宽度和高度滑块\",\n    \"ignore\": \"忽略\",\n    \"fill the width and height sliders manually\": \"手动填充宽度和高度滑块\",\n    \"Smart Preset\": \"智能预设\",\n    \"auto fill the plugin with smart settings, to speed up your working process.\": \"自动填充智能设置的插件，以加快您的工作流程。\",\n    \"Width:\": \"宽度：\",\n    \"maintain the ratio between width and height slider\": \"保持宽度和高度滑块之间的比例\",\n    \"Height:\": \"高度：\",\n    \"CFG Scale:\": \"CFG 比例：\",\n    \"larger value will put more emphasis on the prompt\": \"较大的值将更加强调提示\",\n    \"Denoising Strength:\": \"降噪强度：\",\n    \"Image CFG Scale:\": \"图像 CFG 比例：\",\n    \"Pix2Pix CFG Scale (larger value will put more emphasis on the image)\": \"Pix2Pix CFG 比例（较大的值将更加强调图像）\",\n    \"Mask Blur:\": \"蒙版模糊：\",\n    \"Mask Expansion:\": \"蒙版扩展：\",\n    \"the larger the value the more the mask will expand, '0' means use precise masking, use in combination with the mask blur\": \"值越大，蒙版就会扩展得越多，“ 0”表示使用精确的蒙版，与蒙版模糊一起使用\",\n    \"Inpainting conditioning mask strength:\": \"修复条件蒙版强度：\",\n    \"0 will keep the composition; 1 will allow composition to change\": \"0将保持构图； 1将允许构图发生变化\",\n    \"Mask Content:\": \"蒙版内容：\",\n    \"fill\": \"填充\",\n    \"original\": \"原始\",\n    \"latent noise\": \"潜在噪声\",\n    \"latent nothing\": \"潜在无\",\n    \"Inpaint at Full Res\": \"在全分辨率下修复\",\n    \"Restore Faces\": \"面部修复\",\n    \"Hi Res Fix\": \"高分修复\",\n    \"Upscaler: \": \"放大器：\",\n    \"Hi Res Steps:\": \"高分步数：\",\n    \"Hi Res Scale:\": \"高分比例：\",\n    \"Hi Res Denoising Strength:\": \"高分降噪强度：\",\n    \"Hi Res Output Width:\": \"高分输出宽度：\",\n    \"Hi Res Output Height:\": \"高分输出高度：\",\n    \"Inpaint Padding:\": \"修复填充：\",\n    \"Seed:\": \"种子：\",\n    \"Random\": \"随机\",\n    \"Last\": \"最后\",\n    \"Show Samplers\": \"显示采样器\",\n    \"Sampling Steps:\": \"Sampling Steps:\",\n    \"Select A Script\": \"选择脚本\",\n    \"Activate\": \"激活\",\n    \"Viewer\": \"查看器\",\n    \"Preview\": \"预览器\",\n    \"View your generated images on the canvas\": \"在画布上查看生成的图像\",\n    \"Set Mask\": \"设置蒙版\",\n    \"Set Init Image\": \"设置初始图像\",\n    \"Interrupt\": \"中断\",\n    \"Selection Area\": \"选择区域\",\n    \"Thumbnail Size\": \"缩略图大小\",\n    \"Square 1:1\": \"正方形 1:1\",\n    \"Prompts Library\": \"提示库\",\n    \"Prompt Shortcut: a single word that represent a prompt\": \"提示快捷方式：代表提示的单个单词\",\n    \"Key for new prompt shortcut\": \"新提示快捷方式的键\",\n    \"to be replaced\": \"要被替换的\",\n    \"Value for new prompt shortcut\": \"新提示快捷方式的值\",\n    \"to be replaced with\": \"要被替换为\",\n    \"Add to Prompt Shortcut\": \"添加到提示快捷方式\",\n    \"prompt shortcut\": \"提示快捷方式\",\n    \"Selection a prompt\": \"选择提示词\",\n    \"Refresh Menu\": \"刷新菜单\",\n    \"Load\": \"加载\",\n    \"Save\": \"保存\",\n    \"History\": \"历史记录\",\n    \"history of all the images you generated\": \"您生成的所有图像的历史记录\",\n    \"Load Previous Generations\": \"加载以前的生成\",\n    \"Clear Results\": \"清除结果\",\n    \"Lexica\": \"Lexica\",\n    \"Explore Lexica for prompts and inspiration\": \"探索提示词和灵感的词典\",\n    \"Search:\": \"搜索：\",\n    \"user prompt(text) to Search Lexica\": \"用户提示（文本）搜索词典\",\n    \"User the selected area (image) on canvas to Search Lexica\": \"用户在画布上选择的区域（图像）搜索词典\",\n    \"Image Search\": \"图像搜索\",\n    \"Image Search Engine\": \"图像搜索引擎\",\n    \"ControlNet\": \"ControlNet\",\n    \"The Controlnet Extension is missing from Automatic1111.Please install it to use it through the plugin.\": \"Automatic1111缺少ControlNet扩展。请安装它以通过插件使用它。\",\n    \"ControlNet Preset\": \"ControlNet预设\",\n    \"auto fill the ControlNet with smart settings, to speed up your working process.\": \"自动填充智能设置的ControlNet，以加快您的工作流程。\",\n    \"Set All CtrlNet Images\": \"设置所有 CtrlNet 图像\",\n    \"Disable ControlNet Tab\": \"禁用ControlNet选项卡\",\n    \"Control Net Settings Slot 0\": \"ControlNet设置插槽0\",\n    \"Set CtrlNet Img\": \"设置 CtrlNet 图像\",\n    \"Preview Annotator\": \"预览注释器\",\n    \"Enable\": \"启用\",\n    \"Low VRAM\": \"低显存\",\n    \"Guess Mode\": \"猜测模式\",\n    \"Weight:\": \"权重：\",\n    \"2 will keep the composition; 0 will allow composition to change\": \"2将保持构图； 0将允许构图发生变化\",\n    \"Guidance strength start:\": \"Guidance strength start:\",\n    \"Guidance strength end:\": \"Guidance strength end:\",\n    \"Horde\": \"Horde\",\n    \"Horde Key:\": \"Horde密钥：\",\n    \"Select Backend:\": \"选择后端：\",\n    \"Native Horde\": \"本机 Horde\",\n    \"use the horde with the plugin no need to install anything else\": \"使用插件的 Horde，无需安装其他任何内容\",\n    \"Auto1111 Horde Extension\": \"Auto1111 Horde 扩展\",\n    \"Use the horde extension from Automatic1111 Extension tab\": \"使用 Automatic1111 扩展选项卡中的 Horde 扩展\",\n    \"Auto1111 Only\": \"仅限 Auto1111\",\n    \"use Auto1111 disable the Horde\": \"使用 Auto1111 禁用 Horde\",\n    \"Refresh Models\": \"刷新模型\",\n    \"NSFW\": \"NSFW\",\n    \"Share with LION\": \"与 LION 共享\",\n    \"Extras\": \"额外\",\n    \"Resize\": \"调整大小\",\n    \"Resize scale of current selection size\": \"调整当前选择大小的比例\",\n    \"Generate upscale\": \"生成放大\",\n    \"No work in progress\": \"没有正在进行的工作\",\n    \"Upscaler 1:\": \"放大算法 1：\",\n    \"Upscaler 2:\": \"放大算法 2：\",\n    \"Upscaler 2 visibility:\": \"放大算法 2 可见性：\",\n    \"GFPGAN visibility:\": \"GFPGAN 可见性：\",\n    \"CodeFormer visibility:\": \"CodeFormer 可见性：\",\n    \"CodeFormer weight:\": \"CodeFormer 权重：\",\n    \"Settings\": \"设置\",\n    \"Custom Presets\": \"自定义预设\",\n    \"SD Url:\": \"SD Url：\",\n    \"Submit\": \"提交\",\n    \"use sharp mask\": \"使用锐化蒙版\",\n    \"Smart Object\": \"智能对象\",\n    \"Live Progress Image\": \"实时进度图像\",\n    \"Restore Original Prompt\": \"恢复原始提示\",\n    \"Image Cfg Scale Slider\": \"图像配置比例滑块\",\n    \"Use Silent Mode\": \"使用静默模式\",\n    \"Your PC Speed(optimization):\": \"电脑性能（优化）：\",\n    \"Slow PC\": \"节能模式\",\n    \"Fast PC\": \"高性能模式\",\n    \"Use Colab\": \"使用 Colab\",\n    \"Select Extension:\": \"选择扩展：\",\n    \"Proxy Server\": \"代理服务器\",\n    \"use the proxy server, need to run 'start_server.bat' \": \"使用代理服务器，需要运行“start_server.bat”\",\n    \"Auto111 Extension\": \"SD扩展\",\n    \"use Automatic1111 Photoshop SD Extension, need to install the extension in Auto1111\": \"使用Photoshop SD 扩展，需要在 Auto1111 中安装扩展\",\n    \"None\": \"无\",\n    \"Use the Plugin Only No Additional Component\": \"仅使用插件，无需其他组件\",\n    \"Folder Path (read only):\": \"文件夹路径（只读）：\",\n    \"copy paste the address to access the folder where the images are stored\": \"复制粘贴地址以访问存储图像的文件夹\",\n    \"Get Path\": \"获取路径\",\n    \"Preset Name\": \"预设名称\",\n    \"New Preset\": \"新建预设\",\n    \"Preset Type:\": \"预设类型：\",\n    \"SD Preset\": \"SD 预设\",\n    \"Save Preset\": \"保存预设\",\n    \"Delete Preset\": \"删除预设\",\n    \"The Controlnet Extension is missing from Automatic1111.\\nPlease install it to use it through the plugin.\": \"本地SD中缺少ControlNet扩展。\\n请安装该插件后再使用。\",\n    \"Set CtrlImg\": \"设置原始图\",\n    \"ControlNet Tab\": \"ControlNet\",\n    \"ControlNet Unit\": \"ControlNet #\",\n    \"Select Filter\": \"选择过滤器\",\n    \"Select Module\": \"选择预处理器\",\n    \"Select Model\": \"选择模型\",\n    \"Keep all generated images on the canvas\": \"在画布上保留所有生成图像\",\n    \"Delete all generated images from the canvas\": \"在画布上删除所有生成图像\",\n    \"Keep only the highlighted images\": \"在画布上保留选中的图像\",\n    \"Generate More\": \"生成更多\"\n}\n"
  },
  {
    "path": "i18n/zh_CN/sd-official.json",
    "content": "{\n    \"(0 = default (~0.03); minimum noise strength for k-diffusion noise scheduler)\": \"(0 = 默认 (~0.03); k-diffusion 噪声调度器的最小噪声强度)\",\n    \"(0 = default (~14.6); maximum noise strength for k-diffusion noise schedule)\": \"(0 = 默认 (~14.6); k-diffusion 噪声调度器的最大噪声强度)\",\n    \"(0 = default (7 for karras, 1 for polyexponential); higher values result in a more steep noise schedule (decreases faster))\": \"(0 = 默认 (karras 选择 7, polyexponential 选择 1); 值越高噪声调度曲线越陡峭 (递减更快速))\",\n    \"(0 = disable)\": \"(0 = 禁用)\",\n    \"(0=disable, higher=faster)\": \"(0 = 禁用, 数值越大 = 越快速)\",\n    \"(0 = maximum effect; 1 = minimum effect)\": \"(0 = 最大强度; 1 = 最小强度)\",\n    \"(0 = No limit)\": \"(0 = 无限制)\",\n    \"(0 = no tiling)\": \"(0 = 不分块)\",\n    \"180 Degree Rotation\": \"180 度旋转\",\n    \"1. Get Model Info by Civitai Url\": \"从 Civitai 链接拉取模型信息\",\n    \"-1 means that it is calculated automatically. If both are -1, the size will be the same as the source size.\": \"-1意味着自动计算。如果宽高都是-1，则将与源视频尺寸相同。\",\n    \"1st\": \"第一单元\",\n    \"1st and last digit must be 0 and values should be between 0 and 1. ex:'0, 0.01, 0'\": \"第一个和最后一个数字必须是 0，其他值应介于 0 和 1 之间。如：’0, 0.01, 0’\",\n    \"1st and last digit must be 1. ex:'1, 2, 1'\": \"第一个和最后一个数字必须是 1。例：'1, 2, 1'\",\n    \"2D operator that scales the canvas size, multiplicatively. [static = 1.0]\": \"缩放画布大小的2D操作符，以倍数缩放。[static=1.0]\",\n    \"2D operator to rotate canvas clockwise/anticlockwise in degrees per frame\": \"2D 操作器对每帧动画顺时针/逆时针旋转所指定的角度\",\n    \"2D or 3D animation_mode\": \" 2D 或 3D 动画模式中\",\n    \"2nd\": \"第二单元\",\n    \"360 Panorama to 3D\": \"360°全景图转 3D\",\n    \"3d glb\": \"3D (GLB 格式)\",\n    \"3D Mesh\": \"3D 网格\",\n    \"3D Openpose\": \"3D 骨架模型编辑 （3D Openpose）\",\n    \"3. Download Model\": \"下载模型\",\n    \"3rd\": \"第三单元\",\n    \"4th\": \"第四单元\",\n    \"5th\": \"第五单元\",\n    \"90 Degree Rotation\": \"90 度旋转\",\n    \"A, B or C\": \"A, B 或 C\",\n    \"About\": \"关于\",\n    \"Abs\": \"绝对值\",\n    \"abs. path or url to audio file\": \"音频文件的绝对路径或 URL\",\n    \"abstract\": \"abstract (抽象艺术)\",\n    \"Accent color\": \"强调色\",\n    \"Accent Generate Button\": \"强调生成按钮\",\n    \"Access results in ‘Open results’.\": \"点击“打开最终效果图”获取增强后的图片\",\n    \"According to Live preview subject setting\": \"实时预览主体设置\",\n    \"Accumulation steps\": \"累加步数\",\n    \"Action\": \"操作\",\n    \"Action on existing caption\": \"对已有标注的操作\",\n    \"Actions\": \"其他操作\",\n    \"Activate Selected Script\": \"激活选定脚本\",\n    \"Activation keywords, comma-separated\": \"该模型的触发词，以逗号分隔\",\n    \"Active\": \"启用\",\n    \"Active in img2img (Requires restart)\": \"在图生图中启用 (需重启)\",\n    \"Active in negative prompts (Requires restart)\": \"在反向提示词输入框中启用 (需重启)\",\n    \"Active in third party textboxes [Dataset Tag Editor] [Image Browser] [Tagger] [Multidiffusion Upscaler] (Requires restart)\": \"在第三方文本框中激活标签自动补全  [数据集标签编辑器 (Dataset Tag Editor)] [图库浏览器] [WD1.4标签器 (Tagger)] [Multidiffusion 超分辨率]  (需重启)\",\n    \"Active in third party textboxes [Dataset Tag Editor] (Requires restart)\": \"在第三方输入框中启用  [数据集标签编辑器] (需重启)\",\n    \"Active in txt2img (Requires restart)\": \"在文生图中启用 (需重启)\",\n    \"Adaptive (Gaussian)\": \"自适应（高斯）\",\n    \"Adaptive (Mean)\": \"自适应（平均值）\",\n    \"➕ Add\": \"➕ 添加\",\n    \"Add\": \"添加\",\n    \"Add additional prompting to the prefix, suffix and negative prompt in this screen. The actual prompt fields are ignored.\": \"在此场景下添加附加提示词到前缀、后缀、反向提示词。实际的提示词段会被忽略。\",\n    \"Add additional prompts to the head\": \"在起始添加额外的提示词\",\n    \"Add ALL Displayed\": \"添加所有当前显示的图片\",\n    \"Add a prompt prefix, suffix and the negative prompt in the respective fields. They will be automatically added during processing.\": \"在相应的字段中添加提示词前缀、后缀和反向提示词。它们会在处理过程中被自动添加。\",\n    \"Add a second progress bar to the console that shows progress for an entire job.\": \"向控制台添加第二个进度条以显示作业的整体进度\",\n    \"add audio to video from file/url or init video\": \"从文件/链接或初始视频中提取音频以完成添加\",\n    \"Add background image\": \"添加背景图片\",\n    \"Add Background image\": \"添加背景图片\",\n    \"Add Background Image\": \"添加背景图片\",\n    \"Add Blur\": \"添加模糊\",\n    \"Add Custom Mappings\": \"添加自定义映射\",\n    \"Add Detail\": \"添加细节\",\n    \"Add difference\": \"差额叠加\",\n    \"Add difference:A+(B-C)*alpha\": \"差额叠加: A+(B-C)*α\",\n    \"Added\": \"已添加\",\n    \"Add extended info (seed, prompt) to filename when saving grid\": \"保存网格图时，将扩展信息（随机种子、提示词）添加到文件名\",\n    \"Add hypernetwork to prompt\": \"将 hypernetwork 添加到提示词\",\n    \"Add image number to grid\": \"在网格图上添加图像编号\",\n    \"Add inpaint batch mask directory to enable inpaint batch processing.\": \"添加重绘蒙版目录以启用重绘蒙版功能\",\n    \"Additional Generation Info\": \"附加生成信息\",\n    \"Additional Networks\": \"Additional Networks\",\n    \"Additional options\": \"附加选项\",\n    \"Additional tags (split by comma)\": \"附加标签 (逗号分隔)\",\n    \"Add last frame to keyframes\": \"设置最后一帧为关键帧\",\n    \"Add layer normalization\": \"启用网络层归一化处理\",\n    \"Add Lora hashes to infotext\": \"添加 Lora 的哈希值文本到图片信息中\",\n    \"Add Lora to prompt\": \"将 Lora 添加到提示词\",\n    \"Add LyCORIS to prompt\": \"将 LyCORIS 添加到提示词\",\n    \"Add model hash to generation information\": \"将模型哈希值添加到生成信息\",\n    \"Add model name to generation information\": \"将模型名称添加到生成信息\",\n    \"AddNet Model 1\": \"附加模型 1\",\n    \"AddNet Model 2\": \"附加模型 2\",\n    \"AddNet Model 3\": \"附加模型 3\",\n    \"AddNet Model 4\": \"附加模型 4\",\n    \"AddNet Model 5\": \"附加模型 5\",\n    \"AddNet TEnc Weight 1\": \"附加模型 1 Text Encoder 权重\",\n    \"AddNet TEnc Weight 2\": \"附加模型 2 Text Encoder 权重\",\n    \"AddNet TEnc Weight 3\": \"附加模型 3 Text Encoder 权重\",\n    \"AddNet TEnc Weight 4\": \"附加模型 4 Text Encoder 权重\",\n    \"AddNet TEnc Weight 5\": \"附加模型 5 Text Encoder 权重\",\n    \"AddNet UNet Weight 1\": \"附加模型 1 UNet 权重\",\n    \"AddNet UNet Weight 2\": \"附加模型 2 UNet 权重\",\n    \"AddNet UNet Weight 3\": \"附加模型 3 UNet 权重\",\n    \"AddNet UNet Weight 4\": \"附加模型 4 UNet 权重\",\n    \"AddNet UNet Weight 5\": \"附加模型 5 UNet 权重\",\n    \"AddNet Weight 1\": \"附加模型 1 权重\",\n    \"AddNet Weight 2\": \"附加模型 2 权重\",\n    \"AddNet Weight 3\": \"附加模型 3 权重\",\n    \"AddNet Weight 4\": \"附加模型 4 权重\",\n    \"AddNet Weight 5\": \"附加模型 5 权重\",\n    \"Add new prompts\": \"添加新提示词\",\n    \"Add N to seed when repeating\": \"重复时在种子数上加 N\",\n    \"Add number to filename when saving\": \"在文件名前添加序号\",\n    \"Add program version to generation information\": \"将项目版本添加到生成信息\",\n    \"Add/Remove...\": \"添加/删除...\",\n    \"Add Smart-Steps minimum step and ToMe merging ratio value to generation information.\": \"将优化迭代步数和TOME合并比率数值信息添加到图像生成信息中\",\n    \"Add soundtrack\": \"添加音轨\",\n    \"'add_soundtrack' and 'soundtrack_path' aren't being honoured in \\\"Interpolate an existing video\\\" mode. Original vid audio will be used instead with the same slow-mo rules above.\": \"‘添加音频’和‘音频路径’将不会在‘插入现有视频’模式中执行，原有视频的音频将会使用相同的慢动作规则设置\",\n    \"Add to Sequence X\": \"添加到 X 轴\",\n    \"Add to Sequence Y\": \"添加到 Y 轴\",\n    \"Add trigger words to prompt\": \"一键添加本模型的触发词到提示词输入框\",\n    \"Add weights to Sequence X\": \"将权重添加到 X 序列中\",\n    \"ADetailer CFG scale\": \"After Detailer 提示词引导系数 (CFG scale)\",\n    \"ADetailer CFG scale 2nd\": \"After Detailer 提示词引导系数 (CFG scale)\",\n    \"ADetailer CFG scale 3rd\": \"After Detailer 提示词引导系数 (CFG scale)\",\n    \"ADetailer CFG scale 4th\": \"After Detailer 提示词引导系数 (CFG scale)\",\n    \"ADetailer CFG scale 5th\": \"After Detailer 提示词引导系数 (CFG scale)\",\n    \"ADetailer confidence threshold %\": \"置信阈值 (单位: %)\",\n    \"ADetailer denoising strength\": \"重绘幅度\",\n    \"ADetailer erosion (-) / dilation (+)\": \"图像腐蚀 (-) / 图像膨胀 (+)\",\n    \"ADetailer mask blur\": \"重绘蒙版边缘模糊度\",\n    \"ADetailer model\": \"After Detailer 模型\",\n    \"ADetailer model 2nd\": \"After Detailer 模型\",\n    \"ADetailer model 3rd\": \"After Detailer 模型\",\n    \"ADetailer model 4th\": \"After Detailer 模型\",\n    \"ADetailer model 5th\": \"After Detailer 模型\",\n    \"ADetailer negative prompt\": \"After Detailer 反向提示词\",\n    \"ADetailer negative prompt 2nd\": \"After Detailer 反向提示词\",\n    \"ADetailer negative prompt 3rd\": \"After Detailer 反向提示词\",\n    \"ADetailer negative prompt 4th\": \"After Detailer 反向提示词\",\n    \"ADetailer negative prompt 5th\": \"After Detailer 反向提示词\",\n    \"ADetailer prompt\": \"After Detailer 正向提示词\",\n    \"ADetailer prompt 2nd\": \"After Detailer 正向提示词\",\n    \"ADetailer prompt 3rd\": \"After Detailer 正向提示词\",\n    \"ADetailer prompt 4th\": \"After Detailer 正向提示词\",\n    \"ADetailer prompt 5th\": \"After Detailer 正向提示词\",\n    \"ADetailer steps\": \"After Detailer 迭代步数\",\n    \"ADetailer steps 2nd\": \"After Detailer 迭代步数\",\n    \"ADetailer steps 3rd\": \"After Detailer 迭代步数\",\n    \"ADetailer steps 4th\": \"After Detailer 迭代步数\",\n    \"ADetailer steps 5th\": \"After Detailer 迭代步数\",\n    \"ADetailer x(→) offset\": \"X轴 (→) 偏移\",\n    \"ADetailer y(↑) offset\": \"Y轴 (↑) 偏移\",\n    \"A directory on the same machine where the server is running.\": \"服务器主机上某一目录\",\n    \"A directory or a file\": \"一个文件或文件夹\",\n    \"adjust denoise each img2img batch\": \"调整每个图生图批次的重绘幅度\",\n    \"adjusts the overall contrast per frame [default neutral at 1.0]\": \"调整每帧的整体对比度[默认值为1.0]\",\n    \"Adjusts the size of the image by multiplying the original width and height by the selected value. Ignored if either Resize width to or Resize height to are non-zero.\": \"通过将原宽度和高度乘以选定值来调整图像的大小。如果宽度调整为非零或高度调整为非零，则忽略。\",\n    \"Adjust strength\": \"调整强度\",\n    \"adjust the brightness of the mask. Should be a positive number, with 1.0 meaning no adjustment.\": \"调整蒙版的亮度。该值应该为正数，1.0 表示无调整\",\n    \"Admirable\": \"极好的\",\n    \"ads\": \"含广告\",\n    \"Advanced\": \"高级\",\n    \"Advanced options\": \"高级选项\",\n    \"Affine\": \"仿射\",\n    \"A file on the same machine where the server is running.\": \"服务器所在主机上的文件\",\n    \"Aggressive\": \"激进\",\n    \"Alias from file\": \"从文件读取别名\",\n    \"all\": \"全部\",\n    \"All\": \"全部\",\n    \"all - force multiple  --> idea by redditor WestWordHoeDown, it forces to choose between 2 and 3 image types\": \"all -- 全部 - 强制混合  --> 来自于 redditor: WestWordHoeDown 的创意，强制选择 2-3 种图像类型。\",\n    \"All models in this directory will receive the selected model's metadata\": \"此目录下所有模型都将被粘贴与选中模型完全相同的元数据\",\n    \"all --> normally picks a image type as random. Can choose a ‘other’ more unique type.\": \"all -- 全部 --> 通常会随机选择一个图像类型。可以选择一个 \\\"其它\\\" 更独特的类型。\",\n    \"Allow detectmap auto saving\": \"允许自动保存检测图 (detected maps)\",\n    \"Allow img2img\": \"允许图生图\",\n    \"Allow NSFW\": \"允许成人内容\",\n    \"Allow other script to control this extension\": \"允许其他脚本控制此扩展\",\n    \"allow overwrite\": \"允许覆盖文件\",\n    \"Allow overwrite output-model\": \"允许输出时覆盖同名模型\",\n    \"Allow Preview\": \"允许预览\",\n    \"\\uD83D\\uDD04 All Reset\": \"\\uD83D\\uDD04 全部重置\",\n    \"alpha\": \"α\",\n    \"Alphabetical Order\": \"字母顺序\",\n    \"alpha threshold\": \"透明度阈值\",\n    \"Alpha threshold\": \"透明度阈值\",\n    \"also delete off-screen images\": \"允许同时删除屏幕外的图片\",\n    \"also enable wierd blocky upscale mode\": \"同时启用糟糕的分块放大模式\",\n    \"alternate\": \"交替\",\n    \"Alternatively, use\": \"或者, 使用 \",\n    \"Alternatively, you can enable\": \"或者，您可以启用\",\n    \"Always\": \"保持\",\n    \"Always discard next-to-last sigma\": \"始终舍弃倒数第二个 sigma 值\",\n    \"Always Display Buttons\": \"总是显示按钮\",\n    \"Always print all generation info to standard output\": \"始终将所有生成信息输出到控制台\",\n    \"Always save all generated image grids\": \"始终保存所有生成的网格图\",\n    \"Always save all generated images\": \"始终保存所有生成的图像\",\n    \"A merger of the two checkpoints will be generated in your\": \"合并后的模型将保存在您的\",\n    \"Amount of images to generate\": \"图像生成数量\",\n    \"amount of presence of previous frame to influence next frame, also controls steps in the following formula [steps - (strength_schedule * steps)]\": \"前一帧影响下一帧的存在量，也控制下式中的步数：[steps - (strength_schedule * steps)]\",\n    \"Amount of tries\": \"尝试次数\",\n    \"Amount schedule\": \"数量表\",\n    \"Amount times to repeat upscaling with IMG2IMG (loopback)\": \"通过图生图放大的重复次数 (回送)\",\n    \"and\": \"与\",\n    \"and generate images according to random segmentation which preserve image layout.\": \" 来根据保存图像的布局随机分割生成图像。\",\n    \"and report your problem.\": \"反馈您遇到的问题。\",\n    \"and upscale to the size of the original video.\": \"放大图片到原始视频的尺寸。\",\n    \"A negative prompt to use when generating preview images.\": \"生成预览图像时使用的反向提示词\",\n    \"Angle\": \"角度\",\n    \"angular\": \"angular (棱角)\",\n    \"animal\": \"animal (动物)\",\n    \"animal - A random (fictional) animal. Has a chance to have human characteristics, such as clothing added.\": \"animal - 动物 - 一只随机的（虚构的）动物。可能会拥有人类的特征，如穿衣服。\",\n    \"animation\": \"动画\",\n    \"Animation mode\": \"动画模式\",\n    \"anime\": \"anime (动漫)\",\n    \"Anime\": \"动漫\",\n    \"Anime-inclined great guide (by FizzleDorf) with lots of examples:\": \"很不错的、带有许多示例的动画指南 (由 FizzleDorf 制作) : \",\n    \"anime key visual\": \"anime key visual (动漫主视觉图/海报)\",\n    \"Anime Remove Background\": \"动漫移除背景模式\",\n    \"Annotator resolution\": \"预处理器分辨率\",\n    \"Anti Blur\": \"防模糊\",\n    \"API info may not be necessary for some boorus, but certain information or posts may fail to load without it. For example, Danbooru doesn't show certain posts in search results unless you auth as a Gold tier member.\": \"API 信息对于某些 booru 站点可能不是必需的，但如果没有它，某些信息或图帖可能无法加载。 例如，除非你的 API 验证属于黄金会员，否则 Danbooru 可能不会在搜索结果中显示某些图帖。\",\n    \"API Key\": \"API 密钥\",\n    \"API Keys\": \"API 密钥\",\n    \"append\": \"追加\",\n    \"Append\": \"追加至末尾\",\n    \"Append Caption to File Name\": \"将描述文本追加到文件名之后\",\n    \"Append comma on tag autocompletion\": \"自动添加逗号\",\n    \"Append commas\": \"追加逗号\",\n    \"Append DeepDanbooru to Caption\": \"把 DeepDanbooru 的结果追加到已有的描述文本之后\",\n    \"Append Hires prompts to the end of the original prompts instead of replacing it.\": \"将高分辨率修复提示词追加到原始提示词的末尾，而不是替换它们\",\n    \"Append interrogated prompt at each iteration\": \"在每次迭代时添加何种反推模型反推出的提示词\",\n    \"Append prompts, not replace\": \"追加提示词 (非替换)\",\n    \"Apply\": \"应用\",\n    \"Apply and quit\": \"应用更改并退出\",\n    \"Apply and restart UI\": \"应用更改并重载前端\",\n    \"Apply block weight from text\": \"从文本框应用分块权重值\",\n    \"Apply changes to ALL displayed images\": \"将更改应用于所有已显示的图像\",\n    \"Apply color correction to img2img results to match original colors.\": \"对图生图结果应用颜色校正以匹配原始颜色\",\n    \"Apply horizontal Flip\": \"应用水平翻转\",\n    \"Apply Horizontal Flip\": \"应用水平翻转\",\n    \"Apply if any\": \"应用 (如有)\",\n    \"Apply if any: remove style text from prompt; if any styles are found in prompt, put them into styles dropdown, otherwise keep it as it is.\": \"应用 (如有): 从提示词中删除对应预设样式文本; 将匹配到的预设样式加入下拉菜单\",\n    \"Apply inside mask only\": \"仅使用内部蒙版\",\n    \"Apply mask to original image\": \"应用蒙版到原始图\",\n    \"Apply mask to the Ref Image\": \"应用蒙版到参考图\",\n    \"Apply mask to the result\": \"应用蒙版到结果\",\n    \"Apply only selected scripts to ADetailer\": \"只将选定的脚本应用于 After Detailer\",\n    \"Apply Presets\": \"应用预设\",\n    \"Apply: remove style text from prompt, always replace styles dropdown value with found styles (even if none are found).\": \"应用: 从提示词中删除对应预设样式文本; 总是将下拉菜单内容替换为相应预设样式名 (即使不存在对应预设)\",\n    \"Apply scripts to faces\": \"使用脚本识别脸部\",\n    \"Apply selected styles to current prompt\": \"将所选预设样式插入到当前提示词之后\",\n    \"Apply settings\": \"保存设置\",\n    \"Apply to\": \"应用到\",\n    \"Apply transfer control when loading models\": \"加载模型时应用控制转移\",\n    \"a random seed will be used on each frame of the animation\": \"随机种子将被应用于每帧动画中\",\n    \"architecture\": \"architecture (建筑)\",\n    \"Architecture\": \"架构\",\n    \"Archive filename pattern\": \"压缩包文件名格式\",\n    \"Area\": \"区域\",\n    \"Area (large to small)\": \"面积 (从大到小)\",\n    \"Area lower bound\": \"图片最小面积（宽*高）\",\n    \"Area upper bound\": \"图片最大面积（宽*高）\",\n    \"Arguments are case-sensitive.\": \"参数区分大小写。\",\n    \"Arm Length\": \"手臂长度\",\n    \"art deco\": \"art deco (装饰艺术)\",\n    \"Artistic\": \"艺术\",\n    \"Artists have a major impact on the result. Automatically, it will select between 0-3 artists out of 3483 artists for your prompt.\": \"Artists (艺术家风格) 对图像结果有很大影响。它会自动从 3483 名艺术家中选择 0-3 名艺术家名作为你提示词的一部分。\",\n    \"art nouveau\": \"art nouveau (新艺术运动)\",\n    \"as a UI to define your animation schedules (see the Parseq section in the Init tab).\": \" 作为定义动画参数表的UI (请参见初始化选项卡中的参数定序器部分) .\",\n    \"Ascending\": \"升序\",\n    \"A setting of 1 will cause every frame to receive diffusion in the sequence of image outputs. A setting of 2 will only diffuse on every other frame, yet motion will still be in effect. The output of images during the cadence sequence will be automatically blended, additively and saved to the specified drive. This may improve the illusion of coherence in some workflows as the content and context of an image will not change or diffuse during frames that were skipped. Higher values of 4-8 cadence will skip over a larger amount of frames and only diffuse the “Nth” frame as set by the diffusion_cadence value. This may produce more continuity in an animation, at the cost of little opportunity to add more diffused content. In extreme examples, motion within a frame will fail to produce diverse prompt context, and the space will be filled with lines or approximations of content - resulting in unexpected animation patterns and artifacts. Video Input & Interpolation modes are not affected by diffusion_cadence.\": \"设置为 1 将使每个帧在图像输出序列中生成图像。设置为 2 将每隔一帧进行图像生成，但运动仍然有效。间隔序列期间的图像输出将自动混合、添加并保存到指定驱动器。这可能会改善某些工作流中的一致性错觉，因为图像的内容和上下文在跳过的帧期间不会改变或扩散。更高的间隔值，例如4-8，将跳过更多的帧，并仅生成由生成间隔值设置的“第N”帧。这可能会在动画中产生更多的连续性，但几乎没有机会添加更多的扩散内容。在极端的例子中，帧内的运动将无法产生不同的提示上下文，并且空间将充满线条或近似的内容，从而导致意外的动画模式和伪影。视频输入和插值模式不受生成间隔值的影响。\",\n    \"Aspect Ratio Helper\": \"纵横比助手\",\n    \"Attention Heatmap\": \"关键词热力图\",\n    \"Attention texts for visualization. (comma separated)\": \"待可视化关键词 (逗号分隔)\",\n    \"Audio (if provided) will *not* be transferred to the interpolated video if Slow-Mo is enabled.\": \"音频 (如果提供了) 在以下选项启用时将不会转码压制进帧插值后的视频内：慢动作\",\n    \"Author\": \"作者\",\n    \"Author of this model\": \"此模型的作者\",\n    \"auto\": \"自动\",\n    \"Auto\": \"自动\",\n    \"autocast\": \"自动转换\",\n    \"Autocomplete options\": \"自动补全选项\",\n    \"auto-delete imgs when video is ready\": \"视频完成时自动删除图片\",\n    \"Auto detect size from img2img\": \"从图生图自动检测图像尺寸\",\n    \"Auto focal point crop\": \"自动面部焦点剪裁\",\n    \"automatic\": \"自动\",\n    \"Automatic\": \"自动\",\n    \"“automatic” is entirely build around Latent Couple. It will pass artists and the amount of people/animals/objects to generate in the prompt automatically. Set the prompt compounder equal to the amount of areas defined in Laten Couple.\": \"\\\"自动\\\" 是完全围绕 Latent Couple 构建的。它将在提示词中自动传递艺术家和要生成的人/动物/物件的数量。将提示词混合值设置为等于 Latent Couple 中定义的分区数量。\",\n    \"Auto SAM\": \"自动 SAM\",\n    \"Auto SAM Config\": \"自动 SAM 配置\",\n    \"Auto SAM is mainly for semantic segmentation and image layout generation, which is supported based on ControlNet. You must have ControlNet extension installed, and you should not change its directory name (sd-webui-controlnet).\": \"自动 SAM 基于 ControlNet 的支持，主要用于语义分割和图像分层。需安装 ControlNet 扩展，且不能修改其目录名 (sd-webui-controlnet)。\",\n    \"Auto search port\": \"自动检索端口\",\n    \"Auto segmentation output\": \"自动语义分割输出\",\n    \"Auto-sized crop\": \"自动按比例剪裁缩放\",\n    \"Auto Tagging\": \"自动标记\",\n    \"Auto Tagging option\": \"自动标记选项\",\n    \"Available\": \"可下载\",\n    \"A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result\": \"一个决定随机数生成器输出的值 - 以相同参数和相同种子进行多次生成，会得到相同的多张图像\\n\\uD83C\\uDFB2 将随机种子设置为-1，则每次都会使用一个新的随机数\\n♻️ 复用上一次使用的随机种子，对于固定输出结果有用\",\n    \"A weighted sum will be used for interpolation. Requires two models; A and B. The result is calculated as A * (1 - M) + B * M\": \"最终模型权重是前两个模型按比例相加的结果。需要 A、B 两个模型。计算公式为 A * (1 - M) + B * M\",\n    \"a-z\": \"按首字母正序\",\n    \"- Background\": \"- 背景\",\n    \"background color\": \"背景颜色\",\n    \"Background gradiant color\": \"背景渐变色\",\n    \"Background source(mp4 or directory containing images)\": \"背景源（mp4 或包含图像的目录）\",\n    \"Background type\": \"背景类型\",\n    \"Backup/Restore\": \"备份/恢复\",\n    \"Bake in VAE\": \"嵌入 VAE 模型\",\n    \"Balance between eyes\": \"双眼间距平衡\",\n    \"Balanced\": \"均衡\",\n    \"baroque\": \"baroque (巴洛克)\",\n    \"Base\": \"基层值\",\n    \"Base alpha\": \"α 基数\",\n    \"Base Depth\": \"基础深度\",\n    \"Base Sampler\": \"基础采样器\",\n    \"Basic\": \"基础\",\n    \"Basic info\": \"基本信息\",\n    \"Batch\": \"批量处理\",\n    \"Batch count\": \"总批次数\",\n    \"Batch from Dir\": \"批量处理文件夹\",\n    \"Batch from directory\": \"批量处理文件夹\",\n    \"Batch from Directory\": \"批量处理文件夹\",\n    \"Batch img2img\": \"批量图生图\",\n    \"Batch name\": \"批次名称\",\n    \"batch process\": \"批量处理\",\n    \"Batch Process\": \"批量处理\",\n    \"Batch Run\": \"批量处理\",\n    \"Batch Settings\": \"批量处理设置\",\n    \"batch size\": \"批量大小\",\n    \"Batch size\": \"单批数量\",\n    \"Batch Size\": \"单批数量\",\n    \"Batch-Warp\": \"批量修复\",\n    \"bauhaus\": \"bauhaus (包豪斯)\",\n    \"behind\": \"落后\",\n    \"Below here, you can generate a set of random prompts, and send them to the Workflow prompt field. The generation of the prompt uses the settings in the Main tab.\": \"在下方可以生成一组随机的提示词，并将它们发送到工作流提示词段。提示词的生成使用主菜单中的选项设置。\",\n    \"Benchmark Data\": \"基准测试数据\",\n    \"Benchmarks...\": \"基准测试...\",\n    \"beta\": \"β\",\n    \"Better\": \"更好的\",\n    \"Bicubic\": \"双三次\",\n    \"Bilinear\": \"双线性\",\n    \"Bilingual Localization\": \"双语对照本地化\",\n    \"Bitwise operation\": \"按位 (Bitwise) 运算\",\n    \"Blacklist\": \"黑名单\",\n    \"blend\": \"混合\",\n    \"Blend\": \"混合\",\n    \"Blend factor max\": \"最大混合系数\",\n    \"Blend factor slope\": \"混合斜率系数\",\n    \"Blend mode\": \"混合模式\",\n    \"BLIP: maximum description length\": \"BLIP: 最大描述长度\",\n    \"BLIP: minimum description length\": \"BLIP: 最小描述长度\",\n    \"BLIP: num_beams\": \"BLIP: 集束搜索候选项数目\",\n    \"Block ID\": \"区块 ID\",\n    \"Block size\": \"区块大小\",\n    \"blur\": \"模糊\",\n    \"Blur\": \"模糊\",\n    \"Blur amount:\": \"模糊度：\",\n    \"Blur edges of final overlay mask, if used. Minimum = 0 (no blur)\": \"模糊最终覆盖遮罩的边缘（如果使用）。最小值=0（无模糊）\",\n    \"- Body\": \"- 身体\",\n    \"(booru only)\": \"(仅 booru)\",\n    \"BOOST (multi-resolution merging)\": \"BOOST（分块生成后拼合）\",\n    \"border\": \"边框\",\n    \"Border\": \"边缘\",\n    \"border frames\": \"边界帧数\",\n    \"Border Frames\": \"边界帧数\",\n    \"Border Key Frames\": \"边界关键帧数\",\n    \"bottom-top\": \"下 - 上\",\n    \"box_nms_thresh\": \"箱体数量阈值\",\n    \"Branch\": \"分支\",\n    \"brightness\": \"亮度\",\n    \"Brightness:\": \"明亮度\",\n    \"Bring prompts and setting into one column left side\": \"将正反提示词输入框和设置移动到左侧\",\n    \"built-in\": \"内置\",\n    \"built with gradio\": \"基于 Gradio 构建\",\n    \"Built with Gradio\": \"基于 Gradio 构建\",\n    \"By comma\": \"逗号分组\",\n    \"By default and where supported, SVG-Edit can store your editor preferences and SVG content locally on your machine so you do not need to add these back each time you load SVG-Edit. If, for privacy reasons, you do not wish to store this information on your machine, you can change away from the default option below.\": \"默认情况下，SVG  Edit 可以将设置和SVG图像保存在你的电脑上，因此你不需要在每次使用 SVG Edit 时重复设置。如果出于隐私因素，你不希望将信息保存在你的电脑上，你可以更改以下默认选项。\",\n    \"By default, the algorithm tends to like dark images too much, if you think the output is too dark or not dark enough, you can adjust this ratio. 1 = ‘Do not darken at all’, 0 = ‘A totally black image is ok’, default = 0.9.\": \"默认情况下，算法倾向于生成较黑的图像，如果你认为输出的图像太黑或不够黑，你可以调整最小照明比率。1=\\\"完全不变暗\\\"，0=\\\"全黑的图像\\\"，默认=0.9\",\n    \"By none\": \"不分组\",\n    \"By tokens\": \"词元分组\",\n    \"By vectors\": \"向量分组\",\n    \"By words\": \"单词分组\",\n    \"Cache LDSR model in memory\": \"将 LDSR 模型缓存在内存中\",\n    \"Cadence\": \"生成间隔\",\n    \"calculate dimension of LoRAs(It may take a few minutes if there are many LoRAs)\": \"计算 LoRA 维度 (取决于模型数量，可能需要数分钟)\",\n    \"Calculate hash\": \"计算哈希值\",\n    \"- Camera\": \"- 镜头\",\n    \"Camera Far\": \"镜头最远渲染距离\",\n    \"Camera Focal Length\": \"镜头焦距\",\n    \"Camera Near\": \"镜头最近渲染距离\",\n    \"Camera Parameters\": \"镜头参数\",\n    \"Can be empty,indicating no translation\": \"可以为空，表示无需翻译\",\n    \"Cancel\": \"取消\",\n    \"Cancel generate forever\": \"停止无限生成\",\n    \"Cancel training.\": \"取消训练\",\n    \"canny\": \"canny (硬边缘检测)\",\n    \"Canny\": \"Canny (硬边缘)\",\n    \"Canvas Height\": \"画布高度\",\n    \"Canvas Hotkeys\": \"画布热键\",\n    \"- Canvas Size\": \"- 画布尺寸\",\n    \"Canvas Width\": \"画布宽度\",\n    \"Card height for Extra Networks\": \"扩展模型卡牌高度\",\n    \"Card height for Extra Networks (px)\": \"扩展模型卡牌高度 (px)\",\n    \"Card width for Extra Networks\": \"扩展模型卡牌宽度\",\n    \"Card width for Extra Networks (px)\": \"扩展模型卡牌宽度 (px)\",\n    \"cartoon\": \"cartoon (卡通)\",\n    \"Cartoon\": \"卡通\",\n    \"cascadePSP\": \"CascadePSP\",\n    \"case sensitive\": \"区分大小写\",\n    \"Categorical mask status\": \"分类蒙版状态\",\n    \"⚠ Caution: You should only use these options if you know what you are doing. ⚠\": \"⚠ 警告: 你需要清楚知道自己在做什么才能使用这些选项. ⚠\",\n    \"centered\": \"居中\",\n    \"(CF10) Checkpoint format\": \"(CF10) 模型格式\",\n    \"(CF1) Checkpoint format\": \"(CF1) 模型格式\",\n    \"(CF2) Checkpoint format\": \"(CF2) 模型格式\",\n    \"(CF3) Checkpoint format\": \"(CF3) 模型格式\",\n    \"(CF4) Checkpoint format\": \"(CF4) 模型格式\",\n    \"(CF5) Checkpoint format\": \"(CF5) 模型格式\",\n    \"(CF6) Checkpoint format\": \"(CF6) 模型格式\",\n    \"(CF7) Checkpoint format\": \"(CF7) 模型格式\",\n    \"(CF8) Checkpoint format\": \"(CF8) 模型格式\",\n    \"(CF9) Checkpoint format\": \"(CF9) 模型格式\",\n    \"CFG scale\": \"提示词引导系数 (CFG Scale)\",\n    \"CFG Scale\": \"提示词引导系数 (CFG Scale)\",\n    \"Change brightness\": \"调节亮度\",\n    \"Change checkpoint\": \"更改模型\",\n    \"Change contrast\": \"调节对比度\",\n    \"Change CTRL keybindings to SHIFT\": \"将 CTRL 绑定更改为 SHIFT\",\n    \"Change gain\": \"调节增强强度\",\n    \"Change gamma\": \"调节伽马\",\n    \"Change saturation\": \"调节饱和度\",\n    \"(changes seeds drastically; use CPU to produce the same picture across different videocard vendors)\": \"(显著改变种子效果; 使用 CPU 选项可使不同型号显卡产生相同图像)\",\n    \"(changes seeds drastically; use CPU to produce the same picture across different vidocard vendors)\": \"(大幅改变种子效果, 使用 CPU 选项使不同型号显卡产生相同图像)\",\n    \"Change your brush width to make it thinner if you want to draw something.\": \"绘制内容前请先调整笔刷粗细。\",\n    \"Chant filename (Chants are longer prompt presets)\": \"Chant 文件名（Chant 指较长的提示词预设）\",\n    \"character\": \"character (角色)\",\n    \"Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resolution and lower quality.\": \"廉价的神经网络近似值。与VAE相比速度非常快，但生成的图片水平/垂直分辨率是VAE的四分之一，质量较低\",\n    \"Checkbox\": \"勾选框\",\n    \"Check Console log for Downloading Status\": \"检查控制台日志以查看下载信息\",\n    \"Check for updates\": \"检查更新\",\n    \"Check models' new version\": \"检查模型版本更新\",\n    \"Check models’ new version\": \"检索模型的新版本\",\n    \"Check New Version from Civitai\": \"从 Civitai 上检查版本更新\",\n    \"checkpoint\": \"模型\",\n    \"Checkpoint\": \"模型\",\n    \"Checkpoint A\": \"大模型 A\",\n    \"Checkpoint B\": \"大模型 B\",\n    \"Checkpoint Dropdown\": \"大模型下拉列表\",\n    \"Checkpoint format\": \"模型格式\",\n    \"Checkpoint Format\": \"模型格式\",\n    \"Checkpoint Merger\": \"模型融合\",\n    \"Checkpoint name\": \"模型名\",\n    \"Checkpoints\": \"模型\",\n    \"Checkpoint schedule\": \"模型表\",\n    \"Checkpoints to cache in RAM\": \"保留在内存中的 Stable Diffusion 模型数量\",\n    \"Check progress\": \"查看进度\",\n    \"Check system info for validity\": \"检测系统信息的有效性\",\n    \"Check tensors\": \"检测 tensors\",\n    \"check this box to enable guided images mode\": \"选中该项启用引导图像模式\",\n    \"* check your CLI for outputs\": \"检查 CLI 的输出\",\n    \"Chess\": \"分块\",\n    \"children's illustration\": \"children's illustration (儿童画作)\",\n    \"Choose latent sampling method\": \"选择潜变量采样方法\",\n    \"Choose mode:\": \"选择模式：\",\n    \"Choose preprocessor for semantic segmentation:\": \"选择语义分割的预处理器：\",\n    \"(choose Unet model: Automatic = use one with same filename as checkpoint; None = use Unet from checkpoint)\": \"(选择 Unet 模型: 自动 = 使用与大模型文件名相同的文件; 无 = 使用大模型中的 Unet)\",\n    \"Choose your favorite mask:\": \"请选择你喜欢的蒙版：\",\n    \"circle\": \"圆形\",\n    \"cityscape\": \"cityscape (城市景观)\",\n    \"Civitai Helper\": \"Civitai 助手\",\n    \"Civitai URL\": \"Civitai 链接\",\n    \"Civitai URL or Model ID\": \"Civitai 地址或模型 ID\",\n    \"ckpt\": \"ckpt\",\n    \"Class\": \"组件类别\",\n    \"Classifier Free Guidance Scale - how strongly the image should conform to prompt - lower values produce more creative results\": \"无分类器指导信息影响尺度(Classifier Free Guidance Scale) - 图像应在多大程度上服从提示词 - 较低的值会产生更有创意的结果\",\n    \"clean\": \"clean (绿色、清洁)\",\n    \"Cleanup non-default temporary directory when starting webui\": \"启动 WebUI 时清理非默认临时目录\",\n    \"Clear\": \"清除\",\n    \"Clear ALL filters\": \"清除所有过滤器\",\n    \"Clear prompt\": \"清空提示词内容\",\n    \"Clear selection\": \"清空选择\",\n    \"Clear tag filters\": \"标签清除过滤器\",\n    \"Clear values\": \"清空数值\",\n    \"Click Enhance.\": \"点击“增强”按钮\",\n    \"Click here after the generation to show the video\": \"生成完成后点这里显示视频\",\n    \"click here to gather relevant info\": \"点击此处以收集相关信息\",\n    \"Click to Upload\": \"点击上传\",\n    \"Clip and renormalize\": \"衰减与规格化\",\n    \"CLIP: maximum number of lines in text file\": \"CLIP: 文本文件的最大行数\",\n    \"CLiP model\": \"CLiP 模型\",\n    \"clipseg\": \"CLIP分割\",\n    \"clipseg options\": \"CLIPSeg 选项\",\n    \"Clip skip\": \"CLIP 终止层数\",\n    \"Clip Skip\": \"CLIP 终止层数\",\n    \"CLIP Skip\": \"CLIP 终止层数\",\n    \"CLIP: skip inquire categories\": \"CLIP: 跳过查询类别\",\n    \"CLIP skip schedule\": \"CLIP 终止层数计划表\",\n    \"CLIP tensors checker\": \"Clip tensors 检测\",\n    \"clip_threshold\": \"裁剪阈值\",\n    \"Close\": \"关闭\",\n    \"Closed\": \"关闭\",\n    \"Close Preview\": \"关闭预览\",\n    \"Closer is brighter\": \"越近越亮\",\n    \"Close the video\": \"关闭视频\",\n    \"cloudscape\": \"cloudscape (云景)\",\n    \"cluster num\": \"簇数\",\n    \"Codec\": \"编码器\",\n    \"CodeFormer vis.\": \"CodeFormer 可见程度\",\n    \"CodeFormer visibility\": \"CodeFormer 可见程度\",\n    \"CodeFormer weight\": \"CodeFormer 权重\",\n    \"CodeFormer Weight\": \"CodeFormer 权重\",\n    \"CodeFormer weight (0 = maximum effect, 1 = minimum effect)\": \"CodeFormer 权重 (为 0 时效果最大，为 1 时效果最小)\",\n    \"CodeFormer weight parameter; 0 = maximum effect; 1 = minimum effect\": \"CodeFormer 权重参数；为 0 时效果最大；为 1 时效果最小\",\n    \"Coherence\": \"一致性\",\n    \"collage\": \"collage (拼贴)\",\n    \"color_burn\": \"颜色加深\",\n    \"color_coherence\": \"颜色校正\",\n    \"Color coherence\": \"颜色一致性\",\n    \"Color correction factor\": \"颜色校正系数\",\n    \"color_dodge\": \"颜色减淡\",\n    \"Color force Grayscale\": \"强制颜色空间为灰度\",\n    \"colorful\": \"colorful (多彩)\",\n    \"[color-matcher]\": \"颜色匹配器\",\n    \"Color Matcher Ref Image\": \"颜色匹配器参考图\",\n    \"Color Matcher Ref Image Type\": \"颜色匹配器参考图类型\",\n    \"Color reduce algo\": \"色彩减弱算法\",\n    \"Color sketch inpainting\": \"彩色涂鸦重绘\",\n    \"Color Transfer Method\": \"颜色迁移算法\",\n    \"Color variation\": \"色彩变种\",\n    \"Combinations\": \"组合\",\n    \"Combine axis\": \"拼合方向\",\n    \"Combined\": \"兼有\",\n    \"Combine into one image\": \"拼合为一张图像\",\n    \"comics\": \"comics (美漫)\",\n    \"comma\": \"逗号\",\n    \"Comma separated face number(s)\": \"逗号分隔的面部编号\",\n    \"Comma-separated list of tab names; tabs listed here will appear in the extra networks UI first and in order lsited.\": \"以逗号分割的选项卡名称列表；这里列出的选项卡将首先按顺序出现在扩展模型面板中\",\n    \"Comma-separated list of tags (\\\"artist, style, character, 2d, 3d...\\\")\": \"以逗号分割的标签列表 (如 \\\"artist,style,character,2d,3d...\\\")\",\n    \"Commit\": \"提交\",\n    \"Comp alpha schedule\": \"混合透明度参数表\",\n    \"Compatibility\": \"兼容性\",\n    \"Comp mask type\": \"比较蒙版类型\",\n    \"Component\": \"模型组件\",\n    \"Composable Mask scheduling\": \"可组合的蒙版计划表\",\n    \"Composite audio files extracted from the original video onto the concatenated video.\": \"将原始视频中的音频整合到生成的视频中。\",\n    \"Composite video with previous frame init image in\": \"前一帧初始图像的合成视频在\",\n    \"Comp save extra frames\": \"保存合成过程所有额外帧\",\n    \"Compute Settings\": \"计算设置\",\n    \"Concatenate each frame while crossfading.\": \"在交叉融合运算时串联每一帧。\",\n    \"concept\": \"concept (概念)\",\n    \"concept art\": \"concept art (概念艺术)\",\n    \"concept - Can be a concept, such as “a X of Y”, or an historical event such as “The Trojan War”.\": \"concept - 概念 - 可以是一种概念：例如一个事物的某种特质；或者是一个历史事件，例如 “特洛伊战争“ 。\",\n    \"Config Backup: Config\": \"配置备份：配置\",\n    \"Config file for Adapter models\": \"Adapter 模型配置文件路径\",\n    \"Config file for Control Net models\": \"ControlNet 模型配置文件路径\",\n    \"Config Name\": \"配置名\",\n    \"Config Presets\": \"预设配置\",\n    \"Config-Presets\": \"预设配置\",\n    \"configuration\": \"插件设置\",\n    \"configuration for\": \"详细设置\",\n    \"Connecting\": \"连接中\",\n    \"Connection errored out.\": \"连接出错\",\n    \"Consider a donation on ko-fi! :3\": \"考虑在 ko-fi 上为本插件赞助! :3\",\n    \"Console logging\": \"控制台日志记录\",\n    \"Containing directory\": \"目标模型目录\",\n    \"contrast\": \"对比度\",\n    \"Contrast schedule\": \"对比度参数表\",\n    \"Control Mode\": \"控制模式\",\n    \"Control Mode (Guess Mode)\": \"控制类型 (猜测模式)\",\n    \"ControlNet guidance end\": \"ControlNet 引导结束时机\",\n    \"ControlNet guidance end 2nd\": \"ControlNet 引导结束时机\",\n    \"ControlNet guidance end 3rd\": \"ControlNet 引导结束时机\",\n    \"ControlNet guidance end 4th\": \"ControlNet 引导结束时机\",\n    \"ControlNet guidance end 5th\": \"ControlNet 引导结束时机\",\n    \"ControlNet guidance start\": \"ControlNet 引导介入时机\",\n    \"ControlNet guidance start 2nd\": \"ControlNet 引导介入时机\",\n    \"ControlNet guidance start 3rd\": \"ControlNet 引导介入时机\",\n    \"ControlNet guidance start 4th\": \"ControlNet 引导介入时机\",\n    \"ControlNet guidance start 5th\": \"ControlNet 引导介入时机\",\n    \"ControlNet Inpaint Index\": \"ControlNet 重绘 Unit 序号\",\n    \"ControlNet inpaint model index\": \"ControlNet 的 inpaint 模型启用单元页\",\n    \"ControlNet inpaint not masked\": \"ControlNet 重绘不使用蒙版\",\n    \"ControlNet Inpaint Number\": \"ControlNet 重绘序号\",\n    \"Controlnet input directory\": \"ControlNet 输入目录\",\n    \"ControlNet input directory\": \"ControlNet 的输入目录\",\n    \"ControlNet Input Video Path\": \"ControlNet 输入视频路径\",\n    \"ControlNet is more important\": \"更偏向 ControlNet\",\n    \"ControlNet Mask Video Path\": \"ControlNet 视频蒙版路径\",\n    \"ControlNet model\": \"ControlNet 模型\",\n    \"ControlNet model 2nd\": \"ControlNet 模型\",\n    \"ControlNet model 3rd\": \"ControlNet 模型\",\n    \"ControlNet model 4th\": \"ControlNet 模型\",\n    \"ControlNet model 5th\": \"ControlNet 模型\",\n    \"ControlNet number\": \"ControlNet 序号\",\n    \"ControlNet option\": \"ControlNet 选项\",\n    \"ControlNet Segmentation Index\": \"ControlNet 语义分割 Unit 序号\",\n    \"Controlnet tile model name\": \"Controlnet tile 模型名\",\n    \"ControlNet Video Input\": \"ControlNet 视频输入\",\n    \"ControlNet Video Mask Input\": \"ControlNet 视频蒙版输入\",\n    \"ControlNet weight\": \"ControlNet 权重\",\n    \"Control Net Weight\": \"ControlNet 权重\",\n    \"ControlNet weight 2nd\": \"ControlNet 权重\",\n    \"ControlNet weight 4th\": \"ControlNet 权重\",\n    \"ControlNet weight 5th\": \"ControlNet 权重\",\n    \"Control Net Weight For Face\": \"ControlNet 脸部权重\",\n    \"Controls the strength of the diffusion on the init image. 0 = disabled\": \"控制初始化图像生成器的强度。 0 = 禁用\",\n    \"Control Type\": \"控制类型\",\n    \"Control Weight\": \"控制权重\",\n    \"convert\": \"转换\",\n    \"Convert a 360 spherical panorama to a 3D mesh\": \"将单张 360° 球形全景图转换为 3D 网格\",\n    \"Convert a single 2D image to a 3D mesh\": \"将单张 3D 图像转换为 3D 网格\",\n    \"Convert currently loaded checkpoint into ONNX. The conversion will fail catastrophically if TensorRT was used at any point prior to conversion, so you might have to restart webui before doing the conversion.\": \"将当前加载的 checkpoint 转换为 ONNX 模型。如果在转换前的任意时间加载了 TensorRT, 转换会失败。推荐在转换前重启 webui\",\n    \"Converted checkpoints will be saved in your\": \"转换出的模型将会保存在你的\",\n    \"Convert ONNX to TensorRT\": \"将 ONNX 模型转换为 TensorRT 模型\",\n    \"Convert to ONNX\": \"转换为 ONNX 模型\",\n    \"Convert Unet to ONNX\": \"转换 Unet 为 ONNX 模型\",\n    \"copy\": \"复制\",\n    \"Copy\": \"复制\",\n    \"Copy config from\": \"复制配置文件\",\n    \"Copy image to:\": \"复制当前图像到: \",\n    \"Copy Metadata\": \"开始复制元数据\",\n    \"Copy metadata to other models in directory\": \"将元数据复制到文件夹中的其他模型\",\n    \"\\uD83D\\uDCCB Copy to clipboard\": \"\\uD83D\\uDCCB 复制到剪切板\",\n    \"Copy to ControlNet Inpainting\": \"复制到 ControlNet 重绘\",\n    \"Copy to ControlNet Segmentation\": \"复制到 ControlNet 语义分割\",\n    \"Copy to favorites\": \"复制到收藏夹\",\n    \"Copy to Inpaint Upload & ControlNet Inpainting\": \"复制到局部重绘和 ControlNet 重绘\",\n    \"Copy to txt2img ControlNet Inpainting\": \"复制到文生图 ControlNet 重绘中\",\n    \"cosine\": \"余弦\",\n    \"cosine_with_restarts\": \"周期重启余弦\",\n    \"Cover image\": \"封面图像\",\n    \"Cozy Image Browser\": \"Cozy 图库浏览器\",\n    \"Cozy Nest Image Browser\": \"Cozy Nest 图库浏览器\",\n    \"Create\": \"创建\",\n    \"Create animation\": \"创建动画\",\n    \"Create a text file next to every image with generation parameters.\": \"同时为每个图片创建一个文本文件储存生成参数\",\n    \"Create blank canvas\": \"创建空白画布\",\n    \"Created at:\": \"创建时间：\",\n    \"Create debug image\": \"创建调试(debug)图像\",\n    \"Create embedding\": \"创建嵌入式模型\",\n    \"Create flipped copies\": \"创建水平翻转副本\",\n    \"Create From Hub\": \"从 Huggingface Hub 中创建\",\n    \"Create hypernetwork\": \"创建超网络 (Hypernetwork)\",\n    \"Create New Canvas\": \"创建新画布\",\n    \"Creates animation sequence from denoised intermediate steps with video frame interpolation to achieve desired animation duration\": \"利用视频插值从降噪过程的中间步骤图像中生成动画\",\n    \"Create txt2img canvas\": \"创建文生图画布\",\n    \"CRF\": \"固定码率因子 (CRF)\",\n    \"Crop and resize\": \"裁剪后缩放\",\n    \"Crop and Resize\": \"裁剪后缩放\",\n    \"Crop Images\": \"剪裁图像\",\n    \"crop_n_layers\": \"分层层数\",\n    \"crop_nms_thresh\": \"分层数量阈值\",\n    \"crop_n_points_downscale_factor\": \"分层采样点坍缩因子\",\n    \"crop_overlap_ratio\": \"分层重叠度\",\n    \"Cropping\": \"剪裁\",\n    \"Crop to fit\": \"裁剪以适应宽高比\",\n    \"Crop: top, left, bottom, right\": \"裁切：顶部，左侧，顶部，右侧\",\n    \"Cross-attention\": \"Cross-Attention 优化方案\",\n    \"Cross attention optimization\": \"Cross-Attention 优化方案\",\n    \"Crossfade blend rate\": \"交叉融合强度\",\n    \"Ctrl+up/down precision when editing (attention:1.1)\": \"使用 Ctrl +  ↑/↓ 设置\\\"(tag:1.1)\\\"时的精度\",\n    \"Ctrl+up/down precision when editing <extra networks:0.9>\": \"使用 Ctrl +  ↑/↓ 设置\\\"<extra networks:0.9>\\\"时的精度\",\n    \"Ctrl+up/down word delimiters\": \"可以使用 Ctrl +  ↑/↓ 设置关注度的\\\"提示词分隔符类型\\\"\",\n    \"cubism\": \"cubism (立体主义)\",\n    \"Current\": \"Current (当前帧)\",\n    \"Current Cache\": \"当前缓存目录\",\n    \"currently selected model\": \"当前选择的模型\",\n    \"Current Model\": \"当前模型\",\n    \"Current version\": \"当前版本\",\n    \"Custom Config File\": \"自定义配置文件\",\n    \"Custom Name (Optional)\": \"自定义名称 (可选)\",\n    \"Custom settings file\": \"自定义设置文件\",\n    \"Custom size\": \"自定义尺寸\",\n    \"custum name\": \"自定义名称\",\n    \"Cutoff strongly.\": \"强效分隔\",\n    \"Cut white margin from input\": \"从输入中剪切空白区域\",\n    \"Daam script\": \"Daam 脚本\",\n    \"dark\": \"dark (暗黑)\",\n    \"darken\": \"变暗\",\n    \"Dataset directory\": \"数据集目录\",\n    \"Dataset Directory\": \"数据集目录\",\n    \"Dataset folder structure\": \"数据集文件夹结构\",\n    \"Dataset Images\": \"数据集图片\",\n    \"Dataset Load Settings\": \"数据集加载设置\",\n    \"date\": \"日期\",\n    \"Date\": \"日期\",\n    \"debug\": \"调试\",\n    \"Debug info\": \"调试信息\",\n    \"Debug level\": \"调试等级\",\n    \"Debug log\": \"调试日志\",\n    \"Decode CFG scale\": \"解码提示词引导系数(CFG scale)\",\n    \"Decoder Tile Size\": \"解码器分块大小\",\n    \"Decode steps\": \"解码迭代步数\",\n    \"deepbooru: escape (\\\\) brackets\": \"deepbooru: 转义 (\\\\) 括号\",\n    \"deepbooru: filter out those tags\": \"deepbooru: 过滤以下标签\",\n    \"deepbooru: score threshold\": \"deepbooru: 评分阈值\",\n    \"deepbooru: sort tags alphabetically\": \"deepbooru: 按字母顺序排序标签\",\n    \"deepbooru: use spaces in tags\": \"deepbooru: 在标签间使用空格\",\n    \"Default Image CFG\": \"默认图像引导系数 (CFG)\",\n    \"Defaults\": \"默认设置\",\n    \"Default scoring type\": \"默认评分类型\",\n    \"Default upscaler for image resize operations\": \"默认图像缩放算法\",\n    \"default variables: in \\\\{\\\\}, like \\\\{init_mask\\\\}, \\\\{video_mask\\\\}, \\\\{everywhere\\\\}\": \"默认变量：\\\\{\\\\}，比如 \\\\{init_mask\\\\}, \\\\{video_mask\\\\}, \\\\{everywhere\\\\}\",\n    \"Default view for Extra Networks\": \"默认扩展模型视图\",\n    \"❌ Del\": \"❌ 删除\",\n    \"delete\": \"删除\",\n    \"❌Delete\": \"❌删除\",\n    \"Delete\": \"删除\",\n    \"Delete 0-entries from exif cache\": \"从 EXIF 缓存删除 0-entries\",\n    \"DELETE cannot be undone. The files will be deleted completely.\": \"删除操作无法撤销，文件会被完全删除。\",\n    \"DELETE File(s)\": \"删除文件\",\n    \"Delete Imgs\": \"删除图像\",\n    \"Delete intermediate\": \"删除临时文件\",\n    \"Delete intermediate frames after GIF generation\": \"生成 GIF 后删除临时帧图片\",\n    \"delete next\": \"删除后 N 张\",\n    \"delete or keep raw affected (interpolated/ upscaled depending on the UI section) png imgs\": \"删除或保留受影响的原始 (根据 UI 设置进行插值/放大) PNG 图像\",\n    \"Delete Selected Skeleton (D key)\": \"删除选中骨架 (D 键)\",\n    \"Denoise\": \"降噪\",\n    \"Denoise strength\": \"重绘幅度\",\n    \"Denoising\": \"重绘幅度\",\n    \"Denoising Diffusion Implicit Models - best at inpainting\": \"Denoising Diffusion Implicit models - (DDIM) - 最擅长局部重绘\",\n    \"Denoising strength\": \"重绘幅度\",\n    \"Denoising strength curve\": \"重绘幅度曲线\",\n    \"Denoising strength for face images\": \"脸部重绘幅度\",\n    \"Denoising strength for the entire image\": \"全图重绘幅度\",\n    \"Denoising strength (Inpaint)\": \"局部重绘幅度\",\n    \"Depth\": \"Depth (深度)\",\n    \"depth_leres\": \"depth_leres (LeReS 深度图估算)\",\n    \"depth_leres++\": \"depth_leres++ (LeReS 深度图估算++)\",\n    \"Depth Map\": \"深度图\",\n    \"Depth Maps\": \"深度图\",\n    \"depth_midas\": \"depth_midas (MiDaS 深度图估算)\",\n    \"Depth (Midas/Adabins)\": \"深度模式 (Midas / Adabins)\",\n    \"Depth Output\": \"深度图输出\",\n    \"Depth Prediction\": \"深度估计预处理\",\n    \"Depth Prediction demo\": \"深度估计预处理 Demo\",\n    \"depth_zoe\": \"depth_zoe (ZoE 深度图估算)\",\n    \"Descending\": \"降序\",\n    \"Description\": \"描述\",\n    \"description-based:\": \"基于描述：\",\n    \"Destination directory\": \"目标目录\",\n    \"Destination Directory\": \"目标文件夹\",\n    \"detailed\": \"detailed (细节)\",\n    \"Detailed\": \"详细设置\",\n    \"Detailed Save As\": \"详细保存为\",\n    \"Details\": \"详细设置\",\n    \"Detect from image\": \"从图像中提取\",\n    \"Detect from Image\": \"从图像中提取\",\n    \"Detection\": \"检测\",\n    \"Detection model confidence threshold\": \"检测模型置信阈值\",\n    \"Detection model confidence threshold %\": \"检测模型置信阈值 (单位: %)\",\n    \"Detection model confidence threshold % 2nd\": \"检测模型置信阈值 (单位:  %)\",\n    \"Detection model confidence threshold 2nd\": \"检测模型置信阈值\",\n    \"Detection model confidence threshold % 3rd\": \"检测模型置信阈值 (单位: %)\",\n    \"Detection model confidence threshold 3rd\": \"检测模型置信阈值\",\n    \"Detection model confidence threshold % 4th\": \"检测模型置信阈值 (单位: %)\",\n    \"Detection model confidence threshold 4th\": \"检测模型置信阈值\",\n    \"Detection model confidence threshold % 5th\": \"检测模型置信阈值 (单位: %)\",\n    \"Detection model confidence threshold 5th\": \"检测模型置信阈值\",\n    \"Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies.\": \"决定算法对图像内容的影响程度。设置 0 时，什么都不会改变，而在 1 时，你将获得不相关的图像。\\n值低于 1.0 时，处理的迭代步数将少于“采样迭代步数”滑块指定的步数\",\n    \"deterministic\": \"可复现的\",\n    \"difference\": \"差值\",\n    \"Difference\": \"差分\",\n    \"Diffuse the first frame based on an image, similar to img2img.\": \"基于图像生成第一帧，类似于图生图\",\n    \"digital\": \"digital (数字)\",\n    \"digital art\": \"digital art (数字艺术)\",\n    \"Dilation factor (B)\": \"扩张因子 (B)\",\n    \"Dimension lower bound\": \"最小维度\",\n    \"Dimension upper bound\": \"最大维度\",\n    \"Directly Draw Scribbles\": \"直接绘制线稿\",\n    \"directory.\": \"目录。\",\n    \"Directory for detected maps auto saving\": \"检测图 (detected maps) 保存路径\",\n    \"Directory for saving images using the Save button\": \"“保存”按钮输出文件夹\",\n    \"Directory for saving init images when using img2img\": \"图生图初始图像的保存文件夹\",\n    \"Directory for temporary images; leave empty for default\": \"临时图像目录；默认为空\",\n    \"(directory is hidden if its name starts with \\\".\\\")\": \"(如果目录的名称以 \\\".\\\" 开头, 就会被隐藏)\",\n    \"(directory is hidden if its name starts with \\\".\\\".)\": \"(如果目录的名称以 \\\".\\\" 开头, 就会被隐藏)\",\n    \"Directory name pattern\": \"目录名称格式\",\n    \"Disable\": \"禁用\",\n    \"Disable all extensions\": \"停用所有扩展\",\n    \"Disable at the last loopback time\": \"最后一次回送时禁用\",\n    \"Disable built-in Lora handler\": \"停用内置 Lora 处理器\",\n    \"Disable control type selection\": \"禁用控制类型筛选\",\n    \"disable convert 'AND' to 'BREAK'\": \"不再将 \\\"AND \\\"转换为 \\\"BREAK\\\"\",\n    \"disabled\": \"禁用\",\n    \"Disabled\": \"已禁用\",\n    \"Disable during hires pass\": \"在高清修复过程中停用\",\n    \"Disable for Negative prompt.\": \"为反向提示词禁用本插件效果\",\n    \"Disable image browser (Reload UI required)\": \"禁用 Cozy 图库浏览器 (需重启UI)\",\n    \"Disable image browser (requires reload UI)\": \"禁用 Cozy 图库浏览器 (需要重启)\",\n    \"Disable openpose edit\": \"禁用 openpose 姿态编辑\",\n    \"Disable prompt token counters\": \"禁用提示词词元长度计数器\",\n    \"Disable waves and gradiant background\": \"禁用波纹和背景渐变效果\",\n    \"Disable waves and gradiant background animations\": \"禁用波纹和背景渐变动画\",\n    \"Discard\": \"丢弃\",\n    \"Discard: remove style text from prompt, keep styles dropdown as it is.\": \"丢弃: 从提示词中删除对应预设样式文本, 并保持预设样式下拉菜单不变\",\n    \"Discard weights with matching name\": \"删除匹配键名的表达式的权重\",\n    \"discord server\": \" Discord 服务器\",\n    \"display both english and target language\": \"同时显示英语和目标语言\",\n    \"Display information dialog on Cozy Nest error\": \"显示 Cozy Nest 的信息对话框\",\n    \"Display mode:\": \"显示模式：\",\n    \"Display name for this model\": \"此模型的显示名\",\n    \"Disregard checkpoint information from pasted infotext\": \"忽略粘贴的生成信息文本中的 Stable Diffusion 模型信息\",\n    \"Divergence (3D effect)\": \"发散性（3D 效果）\",\n    \"Divisions\": \"分区方式\",\n    \"Dolly\": \"希区柯克（推轨变焦）\",\n    \"Do not add watermark to images\": \"不在图像上添加水印\",\n    \"Do not append detectmap to output\": \"不输出检测图 (detected maps) (如深度估算图、动作检测图等)\",\n    \"Do not do anything special\": \"什么都不做\",\n    \"Do not fix prompt schedule for second order samplers.\": \"不为二阶采样方法修复提示词作用时间\",\n    \"Do not make DPM++ SDE deterministic across different batch sizes.\": \"保留 DPM++ SDE 采样器 在不同的批次大小之间的结果差异\",\n    \"Do not resize images\": \"不调整图像大小\",\n    \"Do not save grids consisting of one picture\": \"当仅有一张图时不保存网格图\",\n    \"Do not save heatmap images\": \"不保存热力图图像\",\n    \"Do not show any images in results for web\": \"不在浏览器输出结果中显示任何图像\",\n    \"Do not store my preferences or SVG content locally\": \"不在本地保存设置和SVG图像\",\n    \"Don't cache latents\": \"不要缓存潜空间图片\",\n    \"Don't Cache Latents\": \"不要缓存潜空间图片\",\n    \"Don't generate images\": \"不生成图像\",\n    \"Don't generate, only upscale\": \"不生成，仅放大\",\n    \"Don't outfill\": \"不进行填充\",\n    \"Don't Override\": \"不覆盖\",\n    \"Don’t use wierd blocky upscale mode. Or maybe do?\": \"不要用 \\\"糟糕的分块放大模式\\\" ，或者也许可以试试？\",\n    \"double-straight-line\": \"双直线\",\n    \"down\": \"下\",\n    \"Download\": \"下载\",\n    \"Download All files\": \"下载所有文件\",\n    \"\\uD83D\\uDCBE Download image\": \"\\uD83D\\uDCBE 下载图片\",\n    \"Download localization template\": \"导出 localization 模板\",\n    \"Download Max Size Preview\": \"下载最大尺寸预览图\",\n    \"Download missing models upon reading generation parameters from prompt\": \"从生成参数中的提示词读取并下载缺失的模型\",\n    \"Download missing preview images on startup\": \"启动时下载缺失的模型预览图\",\n    \"Download Model\": \"下载模型\",\n    \"Download NSFW (adult) preview images\": \"允许下载含成人内容的预览图\",\n    \"Download system info\": \"下载系统信息\",\n    \"Download the pose as .json file\": \"以 .json 格式保存姿态图\",\n    \"Downscaling\": \"缩小\",\n    \"Drag Me\": \"拖动页面\",\n    \"Drawing\": \"绘画\",\n    \"Drawing Canvas\": \"创建画布\",\n    \"Draw legend\": \"包含图例注释\",\n    \"Draw Legends\": \"包含图例注释\",\n    \"Draw mask\": \"绘制蒙版\",\n    \"dropdown\": \"下拉列表\",\n    \"Dropdown\": \"下拉列表\",\n    \"Drop File Here\": \"拖拽文件到此\",\n    \"Drop Image Here\": \"拖动图像至此\",\n    \"Drop out tags when creating prompts.\": \"创建提示词时丢弃标签(tags)\",\n    \"Drop tabs here to hide them\": \"把选项卡拖到此处隐藏它们\",\n    \"Drop Video Here\": \"拖动视频至此\",\n    \"Dry Run\": \"试运行\",\n    \"Due to ControlNet base extension's inner works it needs its models to be located at 'extensions/deforum-for-automatic1111-webui/models'. So copy, symlink or move them there until a more elegant solution is found. And, as of now, it requires use_init checked for the first run. The ControlNet extension version used in the dev process is a24089a62e70a7fae44b7bf35b51fd584dd55e25, if even with all the other options above used it still breaks, upgrade/downgrade your CN version to this one.\": \"因为 ControlNet 基层插件在内工作，所以需要将 ControlNet 模型置于 “extensions/deforum-for-automatic1111-webui/models”文件夹内。在更优雅的解决方法出现之前，请复制，软链接 symlink 或者移动模型。 \\n同时目前为止，该插件需要在第一次运行时检查 use_init。\\n用于开发进程的 ControlNet 插件版本为 a24089a62e70a7fae44b7bf35b51fd584dd55e25。如果全部按照上文使用还是损坏，请将 ControlNet 版本升级/降级到上述版本。\",\n    \"Due to the limitation of Segment Anything, when there are point prompts, at most 1 box prompt will be allowed; when there are multiple box prompts, no point prompts are allowed.\": \"由于Segment Anything的限制，当有标记点时，最多允许1个箱体标记；当有多个箱体提示时，不允许使用标记点。\",\n    \"duplicate\": \"重复的\",\n    \"Duplicate Skeleton (X-axis)\": \"复制骨架(X 轴)\",\n    \"Duplicate Skeleton (Z-axis)\": \"复制骨架(Z 轴)\",\n    \"Duration\": \"时长\",\n    \"during the run sequence, only frames specified by this value will be extracted, saved, and diffused upon. A value of 1 indicates that every frame is to be accounted for. Values of 2 will use every other frame for the sequence. Higher values will skip that number of frames respectively.\": \"在运行序列期间，只有由该值指定的帧才会被提取、保存和生成。1表示要考虑每个帧。2表示每隔一帧用于序列。较高的值将分别跳过该帧数。\",\n    \"Dynamic Prompts\": \"Dynamic Prompts (动态提示词)\",\n    \"Dynamic Prompts enabled\": \"启用动态提示词\",\n    \"Each image is center-cropped with an automatically chosen width and height.\": \"每张图片都会以自动选择好的宽和高进行中心裁剪\",\n    \"Early stopping parameter for CLIP model; 1 is stop at last layer as usual, 2 is stop at penultimate layer, etc.\": \"CLIP 模型的提前终止层参数；1是像往常一样停在最后一层，2是停在倒数第二层，以此类推\",\n    \"EBSynth Mode\": \"EBSynth 模式\",\n    \"EBSynth Settings\": \"Ebsynth 设置\",\n    \"edit\": \"编辑\",\n    \"Edit\": \"编辑\",\n    \"Edit common tags.\": \"编辑常见标签\",\n    \"editing\": \"后期编辑\",\n    \"Editing Enabled\": \"开启元数据编辑\",\n    \"Edit Openpose\": \"编辑 Openpose\",\n    \"Edit SVG\": \"编辑 SVG\",\n    \"Effect\": \"效果\",\n    \"Effective Block Analyzer\": \"高效区块分析器\",\n    \"EMA (nagetive)\": \"EMA (负)\",\n    \"ema-only\": \"仅保留 EMA 权重\",\n    \"EMA (positive)\": \"EMA (正)\",\n    \"Embedding\": \"嵌入式模型 (Embedding)\",\n    \"Embedding Learning rate\": \"嵌入式模型学习率\",\n    \"Emphasis: use (text) to make model pay more attention to text and [text] to make it pay less attention\": \"强调符：使用 (文字) 使模型更关注该文本，使用 [文字] 减少其关注度\",\n    \"empty cannot be saved\": \"留空时无法保存\",\n    \"empty strings cannot be translated\": \"无法翻译空的文本\",\n    \"Enable\": \"启用\",\n    \"Enable AA for Downscaling.\": \"缩小时使用抗锯齿\",\n    \"Enable AA for Upscaling.\": \"放大时使用抗锯齿\",\n    \"Enable ADetailer\": \"启用 After Detailer\",\n    \"Enable Anti Burn (and everything)\": \"启用 Anti Burn\",\n    \"Enable Autocomplete\": \"启用标签自动补全\",\n    \"Enable Autopruning\": \"启用自动修剪\",\n    \"Enable batch mode\": \"启用批处理模式\",\n    \"Enable Bilingual Localization\": \"启用双语对照翻译插件\",\n    \"Enable CFG-Based guidance\": \"启用基于 CFG 的引导 (CFG-Based guidance)\",\n    \"Enable checkpoint scheduling\": \"启用模型计划表\",\n    \"Enable clear gallery button in txt2img and img2img tabs\": \"在文生图和图生图标签页中启用清除图片输出栏按钮\",\n    \"Enable CLIP skip scheduling\": \"启用 CLIP 终止层数计划表\",\n    \"Enable color correction\": \"启用颜色校正\",\n    \"Enable Control\": \"启用控制\",\n    \"Enable controlnet tile resample\": \"启用 ControlNet 的 tile resample (分块 - 重采样)\",\n    \"enabled\": \"启用\",\n    \"Enabled\": \"启用\",\n    \"Enable Dynamic Thresholding (CFG Scale Fix)\": \"启用动态阈值 (CFG Scale 修复)\",\n    \"Enable emphasis\": \"启用强调符\",\n    \"Enable extra network tweaks\": \"启用扩展网络修改\",\n    \"Enable Face Prompt\": \"启用脸部提示词\",\n    \"Enable full page image viewer\": \"启用网页全屏图像查看器\",\n    \"Enable GroundingDINO\": \"启用 GroundingDINO\",\n    \"Enable guided images mode\": \"启用引导图像模式\",\n    \"Enable Hires. fix+\": \"启用高分修复PLUS\",\n    \"Enable JavaScript aspect ratio controls\": \"启用前端纵横比控制\",\n    \"Enable Jinja2 templates\": \"启用 Jinja2 模板\",\n    \"Enable Maintenance tab\": \"启用 \\\"维护\\\" 选项卡\",\n    \"Enable model compile (experimental)\": \"启用模型编译优化（实验性）\",\n    \"Enable MultiDiffusion\": \"启用 MultiDiffusion\",\n    \"Enable noise multiplier scheduling\": \"启用噪声乘法 (noise multiplier) 调度\",\n    \"Enable optimized monocular depth estimation\": \"启用单色深度估算优化 (optimized monocular depth estimation)\",\n    \"Enable overwrite\": \"允许覆盖\",\n    \"Enable perspective flip\": \"启用透视翻转\",\n    \"Enable pixelization\": \"启用像素化\",\n    \"Enable Pixel Perfect from lllyasviel. Configure your target width and height on txt2img/img2img default panel before preview if you wish to enable pixel perfect.\": \"启用 lllyasviel 的完美像素模式。在预览前，请在文生图/图生图界面配置好图像的目标宽度和高度。\",\n    \"Enable postprocessing operations in txt2img and img2img tabs\": \"在文生图/图生图选项卡中启用后处理操作\",\n    \"Enable quantization in K samplers for sharper and cleaner results\": \"对 K 采样器启用量化以获得更清晰、干净的结果\",\n    \"Enable quantization in K samplers for sharper and cleaner results. This may change existing seeds. Requires restart to apply.\": \"对 K 采样器启用量化以获得更清晰、干净的结果。这可能会改变现有的随机种子。需重启才能应用。\",\n    \"Enable Randomize extension\": \"启用随机化扩展\",\n    \"Enable Region 1\": \"启用区域 1\",\n    \"Enable Region 2\": \"启用区域 2\",\n    \"Enable Region 3\": \"启用区域 3\",\n    \"Enable Region 4\": \"启用区域 4\",\n    \"Enable Region 5\": \"启用区域 5\",\n    \"Enable Region 6\": \"启用区域 6\",\n    \"Enable Region 7\": \"启用区域 7\",\n    \"Enable Region 8\": \"启用区域 8\",\n    \"Enable sampler scheduling\": \"启用采样器计划表\",\n    \"Enable steps scheduling\": \"启用迭代步数计划表\",\n    \"Enable Subseed scheduling\": \"启用第二种子计划表\",\n    \"Enable Tag Autocompletion\": \"启用标签自动补全\",\n    \"Enable tensorboard logging\": \"启用 Tensorboard 日志记录\",\n    \"Enable tensorboard logging.\": \"启用 Tensorboard 日志记录\",\n    \"Enable this to save VRAM.\": \"启用此项以节省显存 (VRAM)。\",\n    \"Enable thumbnail tooltips\": \"启用缩略图工具提示\",\n    \"Enable Tiled Diffusion\": \"启用 Tiled Diffusion\",\n    \"Enable Tiled VAE\": \"启用 Tiled VAE\",\n    \"Enable tooltip on the canvas\": \"启用画布上的工具列提示框\",\n    \"Enable uploading manually created mask to SAM.\": \"启用手动上传蒙版到 SAM。\",\n    \"Enable upscale with extras\": \"启用后期处理放大\",\n    \"Enable Vectorizing\": \"启用矢量化\",\n    \"Enable webcam\": \"开启网络摄像头\",\n    \"Encoder Color Fix\": \"编码器颜色修复\",\n    \"Encoder Tile Size\": \"编码器分块大小\",\n    \"end at this step\": \"结束控制步数\",\n    \"End blur width\": \"结束模糊宽度\",\n    \"Ending Control Step\": \"引导终止时机\",\n    \"End Page\": \"尾页\",\n    \"end the animation at this frame number\": \"达成此帧数后停止生成\",\n    \"Engine\": \"引擎\",\n    \"Enhance\": \"增强\",\n    \"Enhanced img2img\": \"Enhanced img2img (图生图增强)\",\n    \"(ENSD; does not improve anything, just produces different results for ancestral samplers - only useful for reproducing images)\": \"(ENSD: 对图像质量无任何提升, 只为 ancestral 采样方法产生不同的结果 - 仅对复现图像有用)\",\n    \"Enter categody ids, separated by +. For example, if you want bed+person, your input should be 7+12 for ade20k and 59+0 for coco.\": \"在此输入类别 ID，用 + 分隔。例如，如果你想分割出 床 + 人，使用ade20k协议应该输入 7 + 12，使用coco协议应该输入 59 + 0。\",\n    \"Enter category IDs\": \"输入类别ID\",\n    \"Enter hypernetwork Dropout structure (or empty). Recommended : 0~0.35 incrementing sequence: 0, 0.05, 0.15\": \"输入 Hypernetwork Dropout 结构（或留空）\\n推荐：0~0.35\\n递增排序：0、0.05、0.15\",\n    \"Enter hypernetwork layer structure\": \"超网络层结构\",\n    \"Enter input path\": \"填写输入目录\",\n    \"Enter output path\": \"填写输出目录\",\n    \"Enter relative to webui folder or Full-Absolute path, and make sure it ends with something like this: '20230124234916_%09d.png', just replace 20230124234916 with your batch ID. The %05d is important, don't forget it!\": \"输入绝对路径或者以 webui 为根目录的相对路径，同时确认路径结尾类似“20230124234916_%09d.png”。只需要将 20230124234916 替换为你的 batch ID。“%05d”很重要，别忘了！\",\n    \"Equirectangular projection\": \"等距柱状投影图\",\n    \"Erase BG\": \"移除背景图\",\n    \"Error\": \"错误\",\n    \"Error threshold\": \"错误阈值 (%)\",\n    \"Escape brackets\": \"将结果中的括号进行转义处理\",\n    \"Escape parentheses on insertion\": \"插入时转义括号\",\n    \"Eta for ancestral samplers\": \"ancestral 采样方法的 Eta 系数\",\n    \"Eta for DDIM\": \"DDIM 采样方法的 Eta 系数\",\n    \"Eta noise seed delta\": \"Eta 噪声种子偏移量 (ENSD)\",\n    \"etc\": \"其他\",\n    \"Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps higher than 30-40 does not help\": \"Euler Ancestral - 非常有创意，取决于迭代步数不同而生成完全不同的图像，这意味着将迭代步数设置为高于 30-40 不会有任何帮助\",\n    \"ex A.\": \"例 A：\",\n    \"Example: Default args should use 221 as total keyframes.\": \"示例：默认参数应使用 221 作为总关键帧数。\",\n    \"Example flow:\": \"工作流示例: \",\n    \"Examples\": \"例子\",\n    \"Example: seed_schedule could use 0:(5), 1:(-1), 219:(-1), 220:(5)\": \"示例：种子数表可以使用 0:(5), 1:(-1), 219:(-1), 220:(5)\",\n    \"ex B.\": \"例 B：\",\n    \"ex C.\": \"例 C：\",\n    \"Exclude tags (split by comma)\": \"排除标签 (逗号分隔)\",\n    \"Exclude Target (e.g., finger, book)\": \"排除目标（如 finger, book）\",\n    \"exclusion\": \"排除\",\n    \"Excudes (split by comma)\": \"排除 (逗号分隔)\",\n    \"exif keyword\": \"EXIF 关键词\",\n    \"EXIF keyword search\": \"EXIF 关键词搜索\",\n    \"Existing Caption txt Action\": \"对已有标注的 txt 文件的操作\",\n    \"Expanded Mask\": \"扩展后蒙版\",\n    \"Expand Mask\": \"展开蒙版设置\",\n    \"(Experimental, keep cond caches across jobs, reduce overhead.)\": \"(实验性功能；在不同任务中保留缓存以减少开销)\",\n    \"Export\": \"导出\",\n    \"Exported Text\": \"输出文本\",\n    \"Export type\": \"输出类型\",\n    \"expressionism\": \"expressionism (表现主义)\",\n    \"Extension\": \"扩展\",\n    \"Extension index URL\": \"扩展列表地址\",\n    \"Extensions\": \"扩展\",\n    \"Extension State\": \"扩展状态\",\n    \"extension to be installed.\": \"插件\",\n    \"Extension version\": \"扩展版本\",\n    \"extra\": \"额外\",\n    \"Extra\": \"▼\",\n    \"Extra args\": \"额外参数\",\n    \"Extra arguments\": \"额外参数\",\n    \"Extra arguments for trtexec command in plain text form\": \"以纯文本形式填写用于 trtexec 命令的额外参数\",\n    \"Extract frames from the original video.\": \"从原始视频中提取帧。\",\n    \"Extract from frame\": \"提取开始帧\",\n    \"Extract nth frame\": \"提取间隔帧数\",\n    \"Extract to frame\": \"提取结束帧\",\n    \"Extract U-Net features\": \"提取 U-Net 特征值\",\n    \"Extra filename (for small sets of custom tags)\": \"额外文件名（用于小部分的自定义Tag）\",\n    \"Extra generation params\": \"附加生成参数\",\n    \"Extra network card height\": \"扩展模型卡牌高度\",\n    \"Extra network card width\": \"扩展模型卡牌宽度\",\n    \"Extra Networks\": \"扩展模型\",\n    \"Extra networks separator\": \"扩展模型分隔文本\",\n    \"Extra networks tab order\": \"扩展模型类型选项卡顺序\",\n    \"Extra paths to scan for LoRA models, comma-separated. Paths containing commas must be enclosed in double quotes. In the path, \\\" (one quote) must be replaced by \\\"\\\" (two quotes).\": \"扫描低秩微调模型 (LoRA) 的附加目录，以逗号分隔。包含逗号的路径必须用双引号括起来。 在路径中，\\\"（一个引号）必须替换为\\\"\\\"（两个引号）。\",\n    \"Extra path to scan for ControlNet models (e.g. training output directory)\": \"检索 ControlNet 模型的附加目录（如训练输出目录）\",\n    \"extras\": \"后期处理\",\n    \"Extras\": \"后期处理\",\n    \"(extra text to add before <...> when adding extra network to prompt)\": \"(添加扩展模型到提示词时, 在 <...> 之前添加的额外文本)\",\n    \"Extra text to add before <...> when adding extra network to prompt\": \"在向提示词中添加扩展模型标签时在 <…> 之前添加额外文本\",\n    \"Face Area Magnification\": \"脸部区域扩展\",\n    \"Face Crop option\": \"脸部修复选项\",\n    \"Face Crop Resolution\": \"脸部修复分辨率\",\n    \"Face Denoising Strength\": \"脸部去噪强度\",\n    \"Face detection confidence\": \"脸部识别强度\",\n    \"Face Detection Method\": \"人脸识别算法\",\n    \"Face Editor\": \"Face Editor (脸部修复)\",\n    \"Face margin\": \"脸部区域大小\",\n    \"Face restoration\": \"面部修复\",\n    \"Face restoration model\": \"面部修复模型\",\n    \"Face Restore Model\": \"面部修复模型\",\n    \"Fall-off exponent (lower=higher detail)\": \"衰减指数(越小 = 细节越多)\",\n    \"fantasy\": \"fantasy (魔幻)\",\n    \"Far clip\": \"远端衰减\",\n    \"fashion\": \"fashion (时尚)\",\n    \"fast\": \"快速模式\",\n    \"Fast Decoder\": \"使用快速解码器\",\n    \"Fast Encoder\": \"使用快速编码器\",\n    \"Fast Encoder Color Fix\": \"快速编码器颜色修复\",\n    \"Fast Encoder may change colors; Can fix it with more RAM and lower speed.\": \"快速编码器可能会导致颜色偏差；通过使用更大的内存和更慢的速度可以避免这个情况\",\n    \"fauvism\": \"fauvism (野兽派)\",\n    \"favorites\": \"收藏夹\",\n    \"Favorites\": \"收藏夹\",\n    \"Favorites path from settings: log/images\": \"从设置中获取收藏夹路径: log/images\",\n    \"Fetch output folder from a1111 settings (Reload needed to enable)\": \"从 webui 设置中获取输出文件夹 (需重载以启用)\",\n    \"FFmpeg CRF value\": \"FFmpeg CRF 值\",\n    \"FFmpeg path/ location\": \"FFmpeg 路径\",\n    \"FFmpeg settings\": \"FFmpeg 设置\",\n    \"figurativism\": \"figurativism (具象主义)\",\n    \"File\": \"文件\",\n    \"File format for grids\": \"网格图文件格式\",\n    \"File format for images\": \"图片文件后缀（格式）\",\n    \"filename\": \"文件名\",\n    \"Filename\": \"文件名\",\n    \"File Name\": \"文件名\",\n    \"Filename join string\": \"文件名连接用字符串\",\n    \"Filename keyword search\": \"文件名关键词搜索\",\n    \"filename(option)\": \"文件名 (可选)\",\n    \"Filename word regex\": \"文件名用词的正则表达式\",\n    \"Filepath:\": \"文件路径：\",\n    \"File size limit for the above option, MB\": \"上述选项的文件大小限制 (单位: MB)\",\n    \"Files to process\": \"要处理的文件\",\n    \"File type\": \"文件类型\",\n    \"fill\": \"填充\",\n    \"fill down\": \"向下扩展\",\n    \"fill it with colors of the image\": \"用图像颜色 (高强度模糊) 填充\",\n    \"fill it with latent space noise\": \"用潜空间噪声填充\",\n    \"fill it with latent space zeroes\": \"用空白潜空间填充\",\n    \"fill left\": \"向左扩展\",\n    \"fill right\": \"向右扩展\",\n    \"fill up\": \"向上扩展\",\n    \"Filter models by path name\": \"按路径名筛选模型\",\n    \"Filter NSFW content\": \"过滤成人内容 (NSFW)\",\n    \"Filter out following properties (comma seperated). Example film grain, purple, cat\": \"过滤以下提示词包含的属性 (逗号分隔). 例如: film grain, purple, cat\",\n    \"Filter values\": \"过滤值\",\n    \"Final denoising strength\": \"最终重绘幅度\",\n    \"find but bo translated:\": \"已找到但无翻译：\",\n    \"Find your cozy spot on Auto1111's webui\": \"探寻 Auto1111 webui 最舒适的使用方式\",\n    \"First\": \"First (第一生成帧)\",\n    \"First frame as init image\": \"第一帧作为初始化图像\",\n    \"first frame of img2img result\": \"图生图结果的第一帧\",\n    \"FirstGen\": \"FirstGen (处理后生成的第一帧)\",\n    \"First Page\": \"首页\",\n    \"Firstpass height\": \"首次生成高度\",\n    \"Firstpass width\": \"首次生成宽度\",\n    \"Fit video length\": \"适配视频长度\",\n    \"Fix broken CLIP position IDs\": \"修复损坏的 Clip position ID\",\n    \"fixed\": \"固定\",\n    \"Fixed seed\": \"固定种子\",\n    \"Focal point entropy weight\": \"焦点熵权重\",\n    \"Focal point face weight\": \"焦点面部权重\",\n    \"Font color\": \"字体颜色\",\n    \"Font for image grids that have text\": \"网格图文字字体\",\n    \"Font size\": \"字体大小\",\n    \"for ade20k and\": \"来获得 ade20k 类别, 查看\",\n    \"For advanced keyframing with Math functions, see\": \"对于想使用数学函数执行高级关键帧控制的用户，请参阅\",\n    \"For advanced users, you can create a permanent file in \\\\OneButtonPrompt\\\\userfiles\\\\ called antilist.csv\": \"对于专业用户，可以在 \\\\OneButtonPrompt\\\\userfiles\\\\ 中创建一个永久文件，命名为 antilist.csv\",\n    \"Force convert half to float on interpolation (for some platforms)\": \"在插值时强制将半精度浮点数转换为全精度 (适用于部分平台)\",\n    \"Force Reset\": \"强制重置\",\n    \"for coco to get category->id map. Note that coco jumps some numbers, so the actual ID is line_number - 21.\": \"来获得 coco 的类别 -> id 映射。需注意: coco 会跳过部分数字，所以实际 ID 应该是 “划定数字 - 21 (line_number - 21)”\",\n    \"for depth map.\": \"获取深度图更多信息\",\n    \"for detailed explanation.\": \"以了解详细信息。\",\n    \"Foreground Transparency\": \"前景透明度\",\n    \"for explanation of each parameter. If you still cannot understand, use default.\": \"以了解每个参数的含义。如果仍不理解，请保持默认。\",\n    \"FOR HELP CLICK HERE\": \"点击此处获取帮助\",\n    \"For hires fix, use width/height sliders to set final resolution rather than first pass (disables Upscale by, Resize width/height to).\": \"在高分辨率修复中，通过长宽滑块设定最终分辨率 (关闭放大倍率和自适应分辨率设置)\",\n    \"For image processing do exactly the amount of steps as specified\": \"在进行图片处理时，准确执行滑块所指定的迭代步数\",\n    \"For inpainting, include masked composite in results for web\": \"使用重绘时，在网页结果中包含复合蒙版\",\n    \"For inpainting, include the greyscale mask in results for web\": \"使用重绘时，在网页结果中包含灰度蒙版图\",\n    \"For inpainting, save a copy of the greyscale mask\": \"使用重绘时，保存一份灰度蒙版副本\",\n    \"For inpainting, save a masked composite\": \"使用重绘时，保存一份复合蒙版\",\n    \"Format\": \"格式\",\n    \"format: http://127.0.0.1:port\": \"格式: http://127.0.0.1:端口号\",\n    \"For negative prompts, please write your positive prompt, then --neg ugly, text, assymetric, or any other negative tokens of your choice. OR:\": \"对于反向提示词，请写出你的正向提示词，然后添加 --neg ugly,text,assymetric 等您选择的任何其他反向提示词。或者：\",\n    \"For SD upscale, how much overlap in pixels should there be between tiles. Tiles overlap so that when they are merged back into one picture, there is no clearly visible seam.\": \"使用 SD 放大 (SD upscale) 时，分块(Tiles)间的像素重叠宽度\\n分块(Tiles)间重叠有助于使它们合并最终图像时避免过于明显的接缝\",\n    \"for your animation (leave blank to ignore).\": \"用于你的动画中（留空表示忽略）\",\n    \"Found a bug or want to ask for a feature ? Please\": \"发现了一个错误或想请求添加一个功能？请\",\n    \"Found a bug or want to ask for a feature ? Please use\": \"发现了一个错误或想请求添加一个功能？请使用\",\n    \"Found a bug or want to ask for a feature ? Please use   \": \"发现了 Bug 或者有个新的想法？请访问 \",\n    \"Found tags\": \"匹配的标签\",\n    \"fp16\": \"fp16\",\n    \"fp32\": \"fp32\",\n    \"fps\": \"帧率\",\n    \"FPS\": \"帧率\",\n    \"Frame Height\": \"帧高度\",\n    \"Frame Interpolation\": \"帧插值\",\n    \"Frame Interpolation to smooth out, slow-mo (or both) any video.\": \" 进行帧插值来让任何视频获得顺滑的切换效果，慢动作 (或两者皆可)\",\n    \"Frame Interpolation will *not* run if any of the following are enabled: 'Store frames in ram' / 'Skip video for run all'.\": \"帧差值将不会在以下任一选项启用时启动：“保存帧图像到内存” / “跳过视频”\",\n    \"Framerate\": \"帧率\",\n    \"frames per keyframe\": \"每几帧提取1个关键帧\",\n    \"Frames to Video\": \"帧图片转视频\",\n    \"Frame Width\": \"帧宽度\",\n    \"Free GPU\": \"释放显存\",\n    \"Frequency\": \"频率\",\n    \"From (full path)\": \"从 (输入完整路径)\",\n    \"Full\": \"完整\",\n    \"Full res mask\": \"全分辨率蒙版\",\n    \"Full res mask padding\": \"全分辨率蒙版的填充尺寸\",\n    \"(Full = slow but pretty; Approx NN and TAESD = fast but low quality; Approx cheap = super fast but terrible otherwise)\": \"(完整 = 慢但显示效果好; Approx NN 和 TAESD = 快速但低质量; Approx cheap = 超级快但最糟糕)\",\n    \"Gallery height in _absolute_ percent of your screen (not remaining height)\": \"图像输出栏高度占屏幕的百分比 (非剩余高度)\",\n    \"Gamepad repeat period, in milliseconds\": \"游戏手柄回报率 (单位: 毫秒)\",\n    \"gamma\": \"伽马值\",\n    \"Gamma\": \"伽马值\",\n    \"Gap fill technique\": \"间隙填充技术\",\n    \"Gather\": \"生成\",\n    \"Gen\": \"生成\",\n    \"Generate\": \"生成\",\n    \"Generate 3D inpainted mesh. (Sloooow, required for generating videos)\": \"生成优化3D网格 (超慢，用于生成视频)\",\n    \"Generate 4 demo videos with 3D inpainted mesh.\": \"使用 3D 优化网格生成4个演示视频\",\n    \"Generate a checkpoint at the current training level.\": \"保存一个位于当前训练进度的模型文件。\",\n    \"Generate a checkpoint at the current training lvel.\": \"保存一个位于当前训练进度的模型文件。\",\n    \"Generate a .ckpt file when saving during training.\": \"训练中保存时生成一个 ckpt 文件。\",\n    \"Generate a mask image.\": \"生成一个蒙版图像。\",\n    \"Generate Batch\": \"批量处理\",\n    \"Generate Ckpt\": \"创建模型\",\n    \"Generate .ebs file.(ebsynth project file)\": \"生成 .ebs 文件。（Ebsynth 工程文件）\",\n    \"Generate forever\": \"无限生成\",\n    \"Generate human masks\": \"生成人工蒙版\",\n    \"Generate Info\": \"生成信息\",\n    \"Generate inputframes\": \"生成输入帧\",\n    \"Generate layout for batch process\": \"生成批量处理的图像分布\",\n    \"Generate layout for single image\": \"生成单张图像的图像分布\",\n    \"Generate me some prompts!\": \"生成一些提示词\",\n    \"Generate Movie Mode\": \"视频生成模式\",\n    \"Generate Preview\": \"生成预览\",\n    \"Generate preview images every N steps.\": \"每 N 步生成一次预览图像\",\n    \"Generate simple 3D mesh. (Fast, accurate only with ZoeDepth models and no boost, no custom maps)\": \"生成简单3D网格 (快速, 仅适用于 ZoeDepth 模型, 无 Boost, 无 Maps)\",\n    \"Generate stereoscopic image(s)\": \"生成立体图像\",\n    \"Generate video\": \"生成视频\",\n    \"Generate Video\": \"生成视频\",\n    \"Generate video from inpainted(!) mesh.\": \"从深度图生成视频。\",\n    \"Generation Info\": \"生成信息\",\n    \"Generation mode\": \"生成模式\",\n    \"Generation settings:\": \"生成设置:\",\n    \"Generation TEST!!(Ignore Project directory and use the image and mask specified in the main UI)\": \"生成测试!!（忽略工程目录，使用用户界面中指定的图像和蒙版）\",\n    \"Get Civitai Model Info by Model Page URL\": \"从 Civitai 模型页面链接拉取模型信息\",\n    \"*Get depth from uploaded video*\": \"*从上传的视频中获取深度*\",\n    \"Get javascript logs\": \"获取 javascript 日志\",\n    \"Get List\": \"获取列表\",\n    \"Get Model Info from Civitai\": \"从 Civitai 上获取模型信息\",\n    \"Get Model Info from Civitai by URL\": \"从 Civitai 链接获取模型信息\",\n    \"Get sub directories\": \"打开子目录文件夹\",\n    \"GFPGAN vis.\": \"GFPGAN 可见程度\",\n    \"GFPGAN visibility\": \"GFPGAN 可见程度\",\n    \"github\": \"GitHub\",\n    \"Glow\": \"辉光\",\n    \"Glow mode\": \"辉光模式\",\n    \"Gold Pendant\": \"装饰艺术\",\n    \"gore\": \"gore (血腥)\",\n    \"Gothic\": \"哥特\",\n    \"grad\": \"梯度\",\n    \"Gradient accumulation steps\": \"梯度累加步数\",\n    \"Gradient Clipping\": \"梯度 Clip 修剪\",\n    \"Gradient clip value\": \"梯度 Clip 值\",\n    \"Gradio theme\": \"Gradio 主题\",\n    \"Gradio theme (requires restart)\": \"Gradio 主题样式 (需重启)\",\n    \"graffiti\": \"graffiti (涂鸦)\",\n    \"graphic design\": \"graphic design (平面设计)\",\n    \"Great\": \"很好的\",\n    \"greg mode\": \"greg mode (Greg Mike: 美国艺术家)\",\n    \"Grid layout\": \"网格图布局\",\n    \"Grid margins (px)\": \"网格图边框 (单位: 像素)\",\n    \"Grid row count; use -1 for autodetect and 0 for it to be same as batch size\": \"网格图行数； 使用 -1 进行自动检测，使用 0 使其与单批数量相同\",\n    \"GroundingDINO batch progress status\": \"GroundingDINO 批量处理状态\",\n    \"GroundingDINO Box Threshold\": \"GroundingDINO 箱体阈值\",\n    \"GroundingDINO Detection Prompt\": \"GroundingDINO 检测提示词\",\n    \"GroundingDINO Model (Auto download from huggingface)\": \"GroundingDINO 模型 (自动从 huggingface 下载)\",\n    \"GroundingDINO + Segment Anything can achieve [text prompt]->[object detection]->[segmentation]\": \"GroundingDINO + Segment Anything 可以实现 [文本提示词]->[对象检测]->[语义分割]\",\n    \"Group/split table by: (when not started with single quote - so only for prompts, not for merge)\": \"提示词分组方式（非单引号开头时）：\",\n    \"Guess Mode\": \"无提示词引导模式\",\n    \"Guidance End (T)\": \"引导终止时机\",\n    \"Guidance Start (T)\": \"引导介入时机\",\n    \"Guided Images\": \"引导图像\",\n    \"Guided images schedules\": \"引导图像参数表\",\n    \"haku_output\": \"Haku 输出\",\n    \"Half Model\": \"半精度模型\",\n    \"Hands\": \"手掌\",\n    \"Hand Size\": \"手掌尺寸\",\n    \"hard_light\": \"强光\",\n    \"has metadata\": \"有元数据\",\n    \"has user metadata\": \"内嵌用户元数据\",\n    \"Head Size\": \"头部尺寸\",\n    \"height\": \"高度\",\n    \"Height\": \"高度\",\n    \"Height Resolution\": \"高度分辨率\",\n    \"Help\": \"帮助\",\n    \"Help for Jinja2 templates\": \"Jinja2 模板帮助\",\n    \"[here]\": \"[这里]\",\n    \"here\": \"这里\",\n    \"Hidden UI tabs\": \"选择需要隐藏的 UI 标签栏\",\n    \"Hidden UI tabs (requires restart)\": \"需要隐藏的 UI 选项卡 (需要重启)\",\n    \"Hide annotator result\": \"隐藏预处理预览结果\",\n    \"Hide caption\": \"隐藏文本标注\",\n    \"Hide extensions with tags\": \"隐藏含有以下标签的扩展\",\n    \"Hide heatmap images\": \"隐藏热力图图像\",\n    \"Hide samplers in user interface\": \"隐藏用户界面中的采样方法\",\n    \"Hide samplers in user interface (requires restart)\": \"在用户界面中隐藏采样器 (需重启)\",\n    \"high contrast\": \"high contrast (高对比度)\",\n    \"Higher levels increases complexity and randomness of generated prompt\": \"随机等级越高, 生成的提示词越复杂和随机\",\n    \"Highres. fix\": \"高分辨率修复\",\n    \"Hires CFG\": \"高分修复提示词引导系数\",\n    \"hires. fix\": \"高分辨率修复\",\n    \"hiresfix\": \"高清修复\",\n    \"Hires. fix\": \"高分辨率修复 (Hires. fix)\",\n    \"Hires. fix+\": \"高分修复PLUS\",\n    \"Hires fix: show hires prompt and negative prompt\": \"高分辨率修复: 显示高分辨率修复的正反提示词输入框\",\n    \"Hires fix: show hires sampler selection\": \"高分辨率修复: 显示高分采样方法选择栏\",\n    \"Hires. fix+ to do steps optimization\": \"高分修复 PLUS 来优化迭代步数的话\",\n    \"Hires Negative prompt\": \"高分修复反向提示词\",\n    \"Hires Prompt\": \"高分修复正向提示词\",\n    \"Hires sampling method\": \"高分采样方法\",\n    \"Hires Sampling method\": \"高分辨率修复采样方法\",\n    \"Hires steps\": \"高分迭代步数\",\n    \"hires upscaler\": \"高分辨率修复放大算法\",\n    \"Historical\": \"Historical (当前帧前的倒数第二帧)\",\n    \"History\": \"历史记录\",\n    \"Horizontal\": \"水平\",\n    \"Horizontal Mirroring\": \"水平镜像\",\n    \"horizontal split num\": \"水平分割数\",\n    \"Horizontal+Vertical Mirroring\": \"水平+垂直镜像\",\n    \"horror\": \"horror (恐怖)\",\n    \"how closely the image should conform to the prompt. Lower values produce more creative results. (recommended range 5-15)\": \"图像应符合提示词的程度。较低的值会产生更具创造性的结果。（建议范围5-15）\",\n    \"how close to get to the colors of the input frame image/ the amount each frame during a tweening step to use the new images colors\": \"如何接近输入帧图像的颜色 / 在中间计算步骤中使用新图像颜色的每帧数量\",\n    \"How many batches of images to create\": \"创建多少批量次数的图像\",\n    \"How many results to load at once\": \"一次性加载Tag数\",\n    \"How many times to improve the generated image iteratively; higher values take longer; very low values can produce bad results\": \"迭代改进生成的图像的次数；较高的值需要更长的时间；非常低的值会产生不好的结果。\",\n    \"How many times to process an image. Each output is used as the input of the next loop. If set to 1, behavior will be as if this script were not used.\": \"单个图像的处理次数\\n每次输出结果都被用作下一个处理的输入\\n设置为 1 等同于不启用这个脚本\",\n    \"how much the image should look like the previou one and new image frame init. strength schedule might be better if this is higher, around .75 during the keyfames you want to switch on\": \"前一个图像和新的图像帧的初始化强度规划有多大的关系。在你想启用的关键帧中，如果这个数字高一点，大约0.75，可能会更好。\",\n    \"How much to blur the mask before processing, in pixels.\": \"处理前对蒙版进行模糊的强度 (单位: 像素)\",\n    \"How often, in seconds, to flush the pending tensorboard events and summaries to disk.\": \"刷新间隔，单位为秒；将待处理的 Tensorboard 事件和摘要刷新到硬盘\",\n    \"How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something).\": \"变化强度。设为 0 时，将没有效果\\n设为 1 时，你将获得完全产自差异随机种子的图像 (此功能对带有 a 后缀的采样器无效)\",\n    \"hue\": \"色度\",\n    \"HuggingFace Token\": \"HuggingFace 访问令牌\",\n    \"humanoid\": \"humanoid (人形)\",\n    \"humanoid - A random humanoid, males, females, fantasy types, fictional and non-fictional characters. Can add clothing, features and a bunch of other things.\": \"humanoid - 人形 - 一个随机的人形生物，男性、女性、幻想类型，虚构或非虚构的生物。可以添加服装，特征和其它东西。\",\n    \"Humans Masking\": \"人工蒙版\",\n    \"Hybrid composite\": \"混合合成模式\",\n    \"Hybrid motion\": \"混合模式\",\n    \"Hybrid Schedules\": \"混合参数表\",\n    \"Hybrid Settings\": \"合成设置\",\n    \"Hybrid Video\": \"视频合成\",\n    \"Hybrid Video Compositing in 2D/3D Mode\": \"2D/3D 模式下的混合视频合成\",\n    \"Hypernetwork\": \"超网络 (Hypernetwork)\",\n    \"Hypernetwork Learning rate\": \"超网络学习率\",\n    \"Hypernetworks\": \"超网络 (Hypernetworks)\",\n    \"Idea and inspiration by xKean.\": \"这个创意受 xKean 启发。\",\n    \"Idea by redditor jonesaid.\": \"这个创意来自于 redditor: jonesaid 。\",\n    \"If an image is specified below, it will be used with highest priority.\": \"如果在下面指定的一张图像，它将以最高优先级使用。\",\n    \"If an image is too large, crop it from the center.\": \"如果图像太大，则从中心裁剪掉边缘\",\n    \"If Deforum crashes due to CN updates, go\": \"如果 Deforum 由于 ControlNet 版本更新而崩溃，请前往\",\n    \"If enabled, only images will be saved\": \"启用时, 仅保存图片\",\n    \"if enabled, raw imgs will be deleted after a successful video/ videos (upsacling, interpolation, gif) creation\": \"如启用, 则在成功创建视频/其它项目 (放大，插值，gif) 后删除原始图像\",\n    \"If loading of the Yolov5_anime model fails, check\": \"如果 Yolov5_anime 模型加载失败，请查看\",\n    \"If multiple .ebs files are generated, run them all.\": \"如果生成了多个 .ebs 文件，则需要全部运行。\",\n    \"(if not: sort by score)\": \"(如不启用: 按评分排序标签)\",\n    \"(if not: use underscores)\": \"(如不启用: 使用下划线)\",\n    \"If out-* directory already exists in the Project directory, delete it manually before executing.\": \"如果out-*目录已经存在于工程目录中，请在执行前手动删除它。\",\n    \"If \\\"Save a copy of image before doing face restoration.\\\" is enabled, save every image during rolling generation\": \"如果 \\\"在进行面部修复前保存图像副本 \\\" 选项启用，则梯度放大倍数生成时保存每张图像\",\n    \"If setting2prompt width, which width-ratio between both columns (0: minimize setting, 1: 50/50,  6: minimize output gallery column)\": \"设置文生图, 图生图双栏宽度比 (0: 最小化左侧栏宽度, 1: 双侧栏各占50%宽度, 6: 最小化右侧图像输出栏)\",\n    \"If setting2prompt width, which width-ratio between both columns (0: minimize setting, 1: 50/50, 6: minimize output gallery column)\": \"设置文生图, 图生图双栏宽度比 (0: 最小化左侧栏宽度, 1: 双侧栏各占50%宽度, 6: 最小化右侧图像输出栏)\",\n    \"If Smart-Step is enabled, the number of iterations for Hires. fix will never be less than this:\": \"如果启用优化迭代步数，高分辨率修复的迭代步数将永远不会少于本选项设置的数值：\",\n    \"(if the file size is above the limit, or either width or height are above the limit)\": \"(如果图像文件大小超过限制, 或者其宽度或高度超过限制)\",\n    \"If the number of tokens is more than the number of vectors, some may be skipped.\\nLeave the textbox empty to start with zeroed out vectors\": \"如果 Tokens 数量多于向量数量，一些 Tokens 可能会被跳过\\n把输入文本框留空，就可以从清零的向量开始\",\n    \"If the saved image file size is above the limit, or its either width or height are above the limit, save a downscaled copy as JPG\": \"当图像文件大小或尺寸超过限制，另存一份缩小的副本为 JPG 格式\",\n    \"If this values is non-zero, it will be added to seed and used to initialize RNG for noises when using samplers with Eta. You can use this to produce even more variation of images, or you can use this to match images of other software if you know what you are doing.\": \"如果此值非零，它将被添加到种子中，并在使用Eta的采样器时用于初始化随机噪声。\\n你可以用它来产生更多的图像变化，或者用它来模仿其他软件生成的图像，如果你确切知道本选项的功能和你在做什么的话。\",\n    \"If you have already created a background video in Invert Mask Mode([Ebsynth Utility]->[configuration]->[etc]->[Mask Mode]),\": \"如果你已经在反相蒙版模式下创建了一个背景视频（[Ebsynth Utility]->[插件配置]->[其他]->[蒙版模式]），\",\n    \"If you have trouble entering the video path manually, you can also use drag and drop.For large videos, please enter the path manually.\": \"如果你手动输入视频路径嫌麻烦，也可以使用拖放。但是对于大型视频，还是烦请手动输入路径。\",\n    \"If you liked this extension, please\": \"如果你喜欢本插件，请\",\n    \"If you still cannot understand, use default.\": \"如果你仍然无法理解，请保持默认值。\",\n    \"If you want to use the same tagging results the next time you run img2img, rename the file to prompts.txt\": \"如果想在下次运行图生图时使用同样的标记结果，请将该文件重命名为 prompts.txt\",\n    \"If you want to use Width/Height which are not multiples of 64, please change noise_type to 'Uniform', in Keyframes --> Noise.\": \"如果你的宽 / 高参数不是 64 的倍数， 请设置 噪声_类型 选项为 'Uniform‘ , 该选项在关键帧 --> 噪声选项卡内\",\n    \"ignore\": \"无视\",\n    \"Ignore\": \"忽略\",\n    \"Ignore emphasis\": \"忽略强调符号\",\n    \"Ignore: keep prompt and styles dropdown as it is.\": \"忽略: 保持提示词和预设样式下拉菜单不变\",\n    \"Ignore selected VAE for stable diffusion checkpoints that have their own .vae.pt next to them\": \"对于拥有同名 .vae.pt 的模型，忽略外挂 VAE 设置\",\n    \"Ignores step count - uses a number of steps determined by the CFG and resolution\": \"忽略迭代步数 - 使用由 CFG 和分辨率确定的步数\",\n    \"I know what I am doing.\": \"高级选项\",\n    \"Illustration\": \"插画\",\n    \"image\": \"图像\",\n    \"Image\": \"图像\",\n    \"Image browser\": \"图库浏览器\",\n    \"Image Browser\": \"图库浏览器\",\n    \"Image Browser Settings\": \"Cozy 图库浏览器设置\",\n    \"Image CFG Scale\": \"图像引导系数 (CFG)\",\n    \"Image Count\": \"图片数量\",\n    \"Image creation progress preview mode\": \"图像生成过程预览模式\",\n    \"Image Directory\": \"图像目录\",\n    \"Image File\": \"图像文件\",\n    \"Image for Auto Segmentation\": \"用于语义分割的图像\",\n    \"Image for Image Layout\": \"用于图像分布的图像\",\n    \"Image for img2img\": \"图生图的图像\",\n    \"Image for inpainting with mask\": \"用于使用蒙版进行局部重绘的图像\",\n    \"Image for Recognition\": \"识别图像的分辨率\",\n    \"Image for Segment Anything\": \"用于分离的图像\",\n    \"Image height\": \"图像高度\",\n    \"Image Init\": \"图像初始化\",\n    \"Image Layout\": \"图像分布\",\n    \"Image layout status\": \"图像分布状态\",\n    \"Image Parameters\": \"图像参数\",\n    \"Image path\": \"图像路径\",\n    \"Image preview height\": \"预览图高度\",\n    \"Images directory\": \"图像目录\",\n    \"Images filename pattern\": \"图片文件名格式\",\n    \"Images path\": \"图像路径\",\n    \"Images to use for keyframe guidance\": \"用于关键帧引导的图像\",\n    \"Image strength schedule\": \"图像强度参数表\",\n    \"Image to 3D\": \"图转 3D\",\n    \"Image to 3D mesh\": \"图像转 3D 网格\",\n    \"Image to be masked\": \"需要叠加蒙版的图像\",\n    \"Image width\": \"图像宽度\",\n    \"I'm feeling lucky\": \"手气不错\",\n    \"img2img\": \"图生图\",\n    \"img2img alternative test\": \"图生图的替代性测试\",\n    \"img2img CFG\": \"图生图的提示词引导系数\",\n    \"img2img DDIM discretize\": \"图生图 DDIM 离散化\",\n    \"img2img denoise strength\": \"图生图的重绘幅度\",\n    \"img2img-grids\": \"图生图 (网格)\",\n    \"img2img: height of image editor\": \"图生图: 图像编辑器高度\",\n    \"img2img history\": \"图生图历史记录\",\n    \"img2img keyframes.\": \"将关键帧进行图生图。\",\n    \"img2img model to use\": \"图生图使用的模型\",\n    \"img2img padding\": \"图生图的重叠像素宽度\",\n    \"Img2Img Repeat Count (Loop Back)\": \"图生图重复次数（回送）\",\n    \"img2img sampler\": \"图生图的采样方法\",\n    \"img2img Sampling steps\": \"图生图的采样迭代步数\",\n    \"img2img scale\": \"图生图的放大倍数\",\n    \"Img2Img Settings:\": \"图生图设置：\",\n    \"IMG2IMG upscale\": \"图生图放大\",\n    \"img2img upscaler\": \"图生图的放大算法\",\n    \"Import\": \"导入\",\n    \"Import a model from Huggingface.co instead of using a local checkpoint.\": \"从 Huggingface.co 导入模型而非使用本地的模型文件。\",\n    \"Important notes:\": \"重要信息:\",\n    \"Important Notes:\": \"重要事项：\",\n    \"Important notes and Help\": \"重要信息与帮助\",\n    \"*Important* notes on Prompts\": \"对于提示词模式的重要笔记\",\n    \"Import Model from Huggingface Hub\": \"从 Huggingface Hub 载入模型\",\n    \"Import settings from file\": \"从文件导入设置\",\n    \"impressionism\": \"impressionism (印象派)\",\n    \"(improves performance when prompt and negative prompt have different lengths; changes seeds)\": \"(当正向提示词与反向提示词长度不同时可以提升性能; 影响随机性)\",\n    \"IN00\": \"输入层 00\",\n    \"IN01\": \"输入层 01\",\n    \"IN02\": \"输入层 02\",\n    \"IN03\": \"输入层 03\",\n    \"IN04\": \"输入层 04\",\n    \"IN05\": \"输入层 05\",\n    \"IN06\": \"输入层 06\",\n    \"IN07\": \"输入层 07\",\n    \"IN08\": \"输入层 08\",\n    \"IN09\": \"输入层 09\",\n    \"IN10\": \"输入层 10\",\n    \"IN11\": \"输入层 11\",\n    \"IN_A_00\": \"模型 A 输入层 00\",\n    \"IN_A_01\": \"模型 A 输入层 01\",\n    \"IN_A_02\": \"模型 A 输入层 02\",\n    \"IN_A_03\": \"模型 A 输入层 03\",\n    \"IN_A_04\": \"模型 A 输入层 04\",\n    \"IN_A_05\": \"模型 A 输入层 05\",\n    \"IN_A_06\": \"模型 A 输入层 06\",\n    \"IN_A_07\": \"模型 A 输入层 07\",\n    \"IN_A_08\": \"模型 A 输入层 08\",\n    \"IN_A_09\": \"模型 A 输入层 09\",\n    \"IN_A_10\": \"模型 A 输入层 10\",\n    \"IN_A_11\": \"模型 A 输入层 11\",\n    \"IN_B_00\": \"模型 B 输入层 00\",\n    \"IN_B_01\": \"模型 B 输入层 01\",\n    \"IN_B_02\": \"模型 B 输入层 02\",\n    \"IN_B_03\": \"模型 B 输入层 03\",\n    \"IN_B_04\": \"模型 B 输入层 04\",\n    \"IN_B_05\": \"模型 B 输入层 05\",\n    \"IN_B_06\": \"模型 B 输入层 06\",\n    \"IN_B_07\": \"模型 B 输入层 07\",\n    \"IN_B_08\": \"模型 B 输入层 08\",\n    \"IN_B_09\": \"模型 B 输入层 09\",\n    \"IN_B_11\": \"模型 B 输入层 11\",\n    \"Include confident of tags matches in results\": \"在结果中包含标签的匹配置信度\",\n    \"Include images in sub directories\": \"显示子目录中的图片\",\n    \"Include ranks of model tags matches in results.\": \"反推结果包含模型标签匹配等级\",\n    \"Include resource hashes in image metadata (for resource auto-detection on Civitai)\": \"在图像元数据中嵌入资源哈希值 (用于在 Civitai 上自动检测资源)\",\n    \"Include Sub Grids\": \"包含次级网格图\",\n    \"Include Sub Images\": \"包含次级图像\",\n    \"Increment seed after each controlnet batch iteration\": \"在每次 ControlNet 完成批量迭代后增加种子\",\n    \"Index\": \"索引\",\n    \"info\": \"info\",\n    \"Info\": \"信息\",\n    \"Info and links\": \"资讯和链接\",\n    \"Info & Help\": \"信息与帮助\",\n    \"Info, Links and Help\": \"基本信息与帮助链接\",\n    \"Information, comment and share @\": \"信息，评论和分享：\",\n    \"Infotext\": \"文本信息\",\n    \"In FPS\": \"输入帧率\",\n    \"In Frame Count\": \"输入帧数\",\n    \"In \\\"Interpolate existing pics\\\" mode, FPS is determined *only* by output FPS slider. Audio will be added if requested even with slow-mo \\\"enabled\\\", as it does *nothing* in this mode.\": \"在‘插入已有图像’模式中，帧率仅由帧率设置滑块决定。音频将会加入，即使在慢动作模式启用情况下，且在此模式下什么都不会做。\",\n    \"Init\": \"初始化\",\n    \"Initial denoising strength\": \"初始去噪强度\",\n    \"Initialization text\": \"初始化文本\",\n    \"Init image\": \"初始化图像\",\n    \"Init Video\": \"初始视频\",\n    \"In Keyframes tab, you can also set\": \"在关键帧选项卡, 可以设置\",\n    \"in <>, like <apple>, <hair>\": \"<>,比如 <apple>, <hair>\",\n    \"(in megapixels)\": \"(单位: 百万像素)\",\n    \"(in milliseconds)\": \"(单位: 毫秒)\",\n    \"inpaint\": \"局部重绘\",\n    \"Inpaint\": \"局部重绘\",\n    \"Inpaint area\": \"重绘区域\",\n    \"Inpaint Area(Override img2img Inpaint area)\": \"重绘区域（覆盖图生图的重绘区域）\",\n    \"Inpaint at full resolution  2nd\": \"全分辨率局部重绘\",\n    \"Inpaint at full resolution  3rd\": \"全分辨率局部重绘\",\n    \"Inpaint at full resolution  4th\": \"全分辨率局部重绘\",\n    \"Inpaint at full resolution  5th\": \"全分辨率局部重绘\",\n    \"Inpaint at full resolution padding, pixels  2nd\": \"预留像素\",\n    \"Inpaint at full resolution padding, pixels  3rd\": \"预留像素\",\n    \"Inpaint at full resolution padding, pixels  4th\": \"预留像素\",\n    \"Inpaint at full resolution padding, pixels  5th\": \"预留像素\",\n    \"Inpaint batch mask directory (required for inpaint batch processing only)\": \"批量重绘蒙版目录 (仅限批量重绘使用)\",\n    \"Inpaint denoising strength\": \"局部重绘幅度\",\n    \"Inpaint denoising strength 2nd\": \"局部重绘幅度\",\n    \"Inpaint denoising strength 3rd\": \"局部重绘幅度\",\n    \"Inpaint denoising strength 4th\": \"局部重绘幅度\",\n    \"Inpaint denoising strength 5th\": \"局部重绘幅度\",\n    \"inpaint_global_harmonious\": \"Inpaint_Global_Harmonious (重绘 - 全局融合算法)\",\n    \"inpaint height\": \"重绘高度\",\n    \"inpaint height 2nd\": \"重绘高度\",\n    \"inpaint height 3rd\": \"重绘高度\",\n    \"inpaint height 4th\": \"重绘高度\",\n    \"inpaint height 5th\": \"重绘高度\",\n    \"inpainting\": \"重绘\",\n    \"Inpainting\": \"重绘\",\n    \"Inpainting conditioning mask strength\": \"局部重绘时图像调节的蒙版屏蔽强度\",\n    \"Inpaint mask blur\": \"重绘蒙版边缘模糊度\",\n    \"Inpaint mask blur 2nd\": \"重绘蒙版边缘模糊度\",\n    \"Inpaint mask blur 3rd\": \"重绘蒙版边缘模糊度\",\n    \"Inpaint mask blur 4th\": \"重绘蒙版边缘模糊度\",\n    \"Inpaint mask blur 5th\": \"重绘蒙版边缘模糊度\",\n    \"Inpaint masked\": \"重绘蒙版内容\",\n    \"Inpaint not masked\": \"重绘非蒙版内容\",\n    \"inpaint_only\": \"inpaint_only (仅局部重绘)\",\n    \"inpaint_only+lama\": \"inpaint_only+lama (仅局部重绘 + 大型蒙版)\",\n    \"Inpaint only masked\": \"仅重绘蒙版内容\",\n    \"Inpaint only masked 2nd\": \"仅重绘蒙版内容\",\n    \"Inpaint only masked 3rd\": \"仅重绘蒙版内容\",\n    \"Inpaint only masked 4th\": \"仅重绘蒙版内容\",\n    \"Inpaint only masked 5th\": \"仅重绘蒙版内容\",\n    \"Inpaint only masked padding, pixels\": \"仅重绘蒙版区域边缘预留像素\",\n    \"Inpaint only masked padding, pixels 2nd\": \"仅重绘蒙版区域边缘预留像素\",\n    \"Inpaint only masked padding, pixels 3rd\": \"仅重绘蒙版区域边缘预留像素\",\n    \"Inpaint only masked padding, pixels 4th\": \"仅重绘蒙版区域边缘预留像素\",\n    \"Inpaint only masked padding, pixels 5th\": \"仅重绘蒙版区域边缘预留像素\",\n    \"inpaint sketch\": \"涂鸦重绘\",\n    \"Inpaint sketch\": \"涂鸦重绘\",\n    \"Inpaint upload\": \"上传重绘蒙版\",\n    \"inpaint width\": \"重绘宽度\",\n    \"inpaint width 2nd\": \"重绘宽度\",\n    \"inpaint width 3rd\": \"重绘宽度\",\n    \"inpaint width 4th\": \"重绘宽度\",\n    \"inpaint width 5th\": \"重绘宽度\",\n    \"(in pixels)\": \"(单位: 像素)\",\n    \"Input\": \"导入\",\n    \"Input directory\": \"输入目录\",\n    \"Input Directory\": \"输入目录\",\n    \"Input Folder\": \"输入文件夹\",\n    \"Input Image\": \"输入图像\",\n    \"Input images directory\": \"输入图像目录\",\n    \"Input Mesh (.ply | .obj)\": \"输入网格文件 (.ply | .obj)\",\n    \"Input <= Output\": \"输出图像 发送到 输入图像\",\n    \"Input path\": \"输入目录\",\n    \"Input Video\": \"输入视频\",\n    \"In queue...\": \"排队中……\",\n    \"In Res\": \"输入分辨率\",\n    \"(in sampling steps - show new live preview image every N sampling steps; -1 = only show after completion of batch)\": \"(每N个采样步骤更新一次实时预览图像; 设置为-1以在每批次完成后显示)\",\n    \"Insert after\": \"后插\",\n    \"Insert before\": \"前插\",\n    \"Inspect\": \"检查\",\n    \"install\": \"安装\",\n    \"Install\": \"安装\",\n    \"installation\": \"installation (装置艺术)\",\n    \"installed\": \"已安装\",\n    \"Installed\": \"已安装\",\n    \"Install from URL\": \"从网址安装\",\n    \"Installing...\": \"正在安装...\",\n    \"Instead it will pick up all files in the \\\\upscale_me\\\\ folder and upscale them with below settings.\": \"相对应的会用 \\\\upscale_me\\\\ 文件夹中的文件按照下列设置对它们进行放大。\",\n    \"instructs the run to start from a specified point\": \"指示运行从指定点开始\",\n    \"integrations\": \"集成功能\",\n    \"interactive splines and Bezier curves\": \"交互式样条曲线和贝赛尔曲线\",\n    \"Intermediate files path\": \"临时文件路径\",\n    \"Intermediate results may look better than the end results. /!\\\\ Intermediate results are cleaned after each run, save them elsewhere if you want to keep them.\": \"中间的结果可能比最终结果看起来更好。提示: 中间的结果在每次运行后都会被清理，如果你想保留它们，就把它们保存在其它地方\",\n    \"internal order\": \"内部排序\",\n    \"Interpolation\": \"插值\",\n    \"interpolation method\": \"插值模式\",\n    \"Interpolation method\": \"插值算法\",\n    \"Interpolation Method\": \"融合算法\",\n    \"Interrogate\": \"反推提示词\",\n    \"Interrogate\\nCLIP\": \"CLIP\\n反推\",\n    \"Interrogate\\nDeepBooru\": \"DeepBooru\\n反推\",\n    \"Interrogate: keep models in VRAM\": \"反推：将模型保留在显存中\",\n    \"Interrogate Options\": \"反推设置\",\n    \"Interrogate Result\": \"反推结果\",\n    \"Interrogate Selected Image\": \"反推所选图片\",\n    \"Interrogator\": \"反推模型\",\n    \"Interrogator Settings\": \"反推器设置\",\n    \"interrupt\": \"中止\",\n    \"Interrupt\": \"中止\",\n    \"In the main tab, set the subject to humanoids\": \"在主菜单标签页, 设置主题为 humanoids (人形)\",\n    \"In the prefix prompt field then add for example: Art by artistname, 2 people\": \"然后在前缀提示词段中添加示例:  Art by artistname, 2 people\",\n    \"(in tokens - for texts shorter than specified, if they don't fit into 75 token limit, move them to the next 75 token chunk)\": \"(Token 中短于指定长度的提示词, 如果它们不符合 75 Tokens 的上限, 则将他们移至下一个 75 Tokens 组中)\",\n    \"Invert\": \"反相\",\n    \"Invert colors\": \"反转颜色\",\n    \"Invert colors if your image has white background.\": \"对于白色背景图片请开启颜色反转。\",\n    \"Invert DepthMap\": \"反转深度图\",\n    \"Invert DepthMap (black=near, white=far)\": \"反转深度图（黑色=近，白色=远）\",\n    \"invert (from white bg & black line)\": \"invert (白底黑线反色)\",\n    \"Invert Input Color\": \"反转输入颜色\",\n    \"Invert mask\": \"反转蒙版\",\n    \"Invert selection\": \"反向选择\",\n    \"is also a good option, it makes compact math formulae for Deforum keyframes by selecting various waveforms.\": \" 也是一个很好的选择，它可以通过选择各种波形来为 Deforum 关键帧生成严谨的数学公式.\",\n    \"is equivalent to\": \"等同于\",\n    \"is experimental functions and NO PROOF of effectiveness.\": \" 为实验性功能，不保证有效性。\",\n    \"is set,\": \"已经设置数值，\",\n    \"Iterate seed every line\": \"每行输入都换一个随机种子\",\n    \"It takes time, just wait. Check console log for detail\": \"检查需要一段时间，请耐心等待。检查控制台日志以查看详情。\",\n    \"It will then recognize the body type and not generate it. It also recognizes the keyword wearing, and will not generate an outfit.\": \"然后，它将识别体型来避免生成对应体型。它同样能识别关键词 \\\"穿着\\\"，避免生成服装。\",\n    \"It will translate prompt from your native language into English. So, you can write prompt with your native language.\": \"这会将您输入的提示词翻译为英文。因此，您可以直接用母语输入提示词。\",\n    \"I want to preview GroundingDINO detection result and select the boxes I want.\": \"我想预览 GroundingDINO 的结果并选择我想要的箱体。\",\n    \"Javascript logs\": \"Javascript 日志\",\n    \"JavaScript selection method\": \"前端选择样式\",\n    \"Jitter step:\": \"抖动步数: \",\n    \"Jitter the seeds of sub-generations when doing a rolling generation (Still deterministic)\": \"在进行梯度放大倍数生成时, 对子代生成的随机种子进行抖动 (图像依旧可复现)\",\n    \"Join the\": \"加入\",\n    \"- Joints and Limbs\": \"- 关节和四肢\",\n    \"json path\": \"json 路径\",\n    \"JSON Validator\": \"JSON 检查器中检查\",\n    \"Just resize\": \"仅调整大小\",\n    \"Just Resize\": \"仅调整大小\",\n    \"Just resize (latent upscale)\": \"调整大小 (潜空间放大)\",\n    \"Keep -1 for seeds\": \"保持种子随机\",\n    \"Keep at 1 for normal behavior.\\nSet to different values to compound that many prompts together. My suggestion is to try 2 first.\": \"设置为 1 保持正常行为。\\n设置其他数值来混合更多提示词。我的建议是先尝试设置为 2 。\",\n    \"Keep blank if you don't have mask\": \"如果没有遮罩, 请保持空白\",\n    \"Keep Imgs\": \"保留原图\",\n    \"Keep models in VRAM\": \"将模型保留在显存中\",\n    \"Keep occlusion edges\": \"保持边缘封闭\",\n    \"Keep original size\": \"保持原始尺寸\",\n    \"Keep temp images\": \"保留临时图像\",\n    \"Keep the Ratio\": \"保持图像比例\",\n    \"keep whatever was there originally\": \"保留原来的图像，不进行预处理\",\n    \"Kernel schedule\": \"Kernel 值表\",\n    \"Keyframes\": \"关键帧\",\n    \"Keyframes: animation settings (animation mode, max frames, border)\": \"关键帧：动画设置（动画模式，最大帧数，边界）\",\n    \"Keyframes: coherence (color coherence & cadence)\": \"关键帧：一致性（颜色一致性和间隔）\",\n    \"Keyframes: depth warping\": \"关键帧：深度扭曲\",\n    \"Keyframes: generation settings (noise, strength, contrast, scale).\": \"关键帧：通用设置（噪点，强度，对比度，缩放）\",\n    \"Keyframes: motion parameters for 2D and 3D (angle, zoom, translation, rotation, perspective flip).\": \"关键帧：2D 和 3D 的运动参数（角度，缩放，变换，旋转，透视翻转）\",\n    \"Keywords\": \"关键词\",\n    \"Label\": \"标记\",\n    \"LAB is a more linear approach to mimic human perception of color space - a good default setting for most users.\": \"LAB 是一种更为线性的方法，可以模拟人类对色彩空间的感知——这是大多数用户的一个很好的默认设置。\",\n    \"ladder\": \"阶梯式\",\n    \"Lanczos\": \"Lanczos\",\n    \"landscape\": \"landscape (景观)\",\n    \"landscape - A landscape or a landscape with a building.\": \"landscape - 景观 - 一般景观或有建筑的景观。\",\n    \"Last message\": \"最后输出信息\",\n    \"Latent Mirror mode\": \"潜空间镜像应用模式\",\n    \"Latent Mirror style\": \"潜空间镜像方式\",\n    \"latent noise\": \"潜空间噪声\",\n    \"latent nothing\": \"空白潜空间\",\n    \"Latent tile batch size\": \"潜空间分块单批数量\",\n    \"Latent tile height\": \"潜空间分块高度\",\n    \"Latent tile overlap\": \"潜空间分块重叠\",\n    \"Latent tile width\": \"潜空间分块宽度\",\n    \"latest\": \"最新\",\n    \"Layer1\": \"图层 1\",\n    \"Layer1 mask blur\": \"图层 1 蒙版模糊度\",\n    \"Layer1 mask strength\": \"图层 1 蒙版强度\",\n    \"Layer1 opacity\": \"图层 1 透明度\",\n    \"Layer2\": \"图层 2\",\n    \"Layer2 mask blur\": \"图层 2 蒙版模糊度\",\n    \"Layer2 mask strength\": \"图层 2 蒙版强度\",\n    \"Layer2 opacity\": \"图层 2 透明度\",\n    \"Layer3\": \"图层 3\",\n    \"Layer3 mask blur\": \"图层 3 蒙版模糊度\",\n    \"Layer3 mask strength\": \"图层 3 蒙版强度\",\n    \"Layer3 opacity\": \"图层 3 透明度\",\n    \"Layer4\": \"图层 4\",\n    \"Layer4 mask blur\": \"图层 4 蒙版模糊度\",\n    \"Layer4 mask strength\": \"图层 4 蒙版强度\",\n    \"Layer4 opacity\": \"图层 4 透明度\",\n    \"Layer5\": \"图层 5\",\n    \"Layer5 mask blur\": \"图层 5 蒙版模糊度\",\n    \"Layer5 mask strength\": \"图层 5 蒙版强度\",\n    \"Layer5 opacity\": \"图层 5 透明度\",\n    \"Layers\": \"图层\",\n    \"Lazy\": \"保守\",\n    \"LDSR processing steps. Lower = faster\": \"LDSR 处理步数。越少越快\",\n    \"Learning rate\": \"学习率\",\n    \"Learning Rate\": \"学习率\",\n    \"Learning Rate Scheduler\": \"学习率调度器\",\n    \"Learning Rate Warmup Steps\": \"学习率预热步数\",\n    \"Leave blank to save images to the default path.\": \"留空以将图像保存到默认路径\",\n    \"Leave blank to save images to the same path.\": \"留空以将图像保存到相同路径\",\n    \"Leave empty for auto\": \"留空时自动生成\",\n    \"Leave empty for default main branch\": \"留空以使用默认分支\",\n    \"Leave empty to use img2img batch controlnet input directory\": \"留空以使用图生图批量处理 ControlNet 输入目录\",\n    \"Leave empty to use input directory\": \"留空以使用普通输入目录\",\n    \"Leave empty to use the same name as model and put results into models/Unet-onnx directory\": \"留空以使用与 checkpoint 模型相同的名称, 并将转换出的模型放入 models/Unet-onnx 目录\",\n    \"Leave empty to use the same name as onnx and put results into models/Unet-trt directory\": \"留空以使用与 onnx 模型相同的名称, 并将转换出的模型放入 models/Unet-trt 目录\",\n    \"Leave the prompt field empty\": \"提示词段留空\",\n    \"Leave this alone unless you know what you are doing\": \"不明白这个选项的意思的话最好不要动\",\n    \"left\": \"左\",\n    \"Left click the image to add one positive point (black dot). Right click the image to add one negative point (red dot). Left click the point to remove it.\": \"左键点击图像添加一个黑色的正向标记点（想提取的部分）。右键点击图像添加一个红色的反向标记点（不想提取的部分）。左键再次点击可以删除标记点。\",\n    \"left-right\": \"左 - 右\",\n    \"Legacy hash\": \"旧哈希值\",\n    \"Leg Length\": \"腿部长度\",\n    \"Len\": \"长度\",\n    \"Lerp\": \"线性插值\",\n    \"Licenses\": \"许可协议\",\n    \"light\": \"light (照明艺术)\",\n    \"lighten\": \"变亮\",\n    \"like here\": \"链接\",\n    \"Linear\": \"线性\",\n    \"linear_burn\": \"线性加深\",\n    \"linear_dodge\": \"线性减淡\",\n    \"linear_light\": \"线性光\",\n    \"Lineart\": \"Lineart (线稿)\",\n    \"lineart_anime\": \"lineart_anime (动漫线稿提取)\",\n    \"lineart_anime_denoise\": \"lineart_anime_denoise (动漫线稿提取 - 去噪)\",\n    \"lineart_coarse\": \"lineart_coarse (粗略线稿提取)\",\n    \"lineart_realistic\": \"lineart_realistic (写实线稿提取)\",\n    \"lineart_standard (form white bg & black line)\": \"lineart_standard (标准线稿提取 - 白底黑线)\",\n    \"lineart_standard (from white bg & black line)\": \"lineart_standard (标准线稿提取 - 白底黑线反色)\",\n    \"line drawing\": \"line drawing (线描)\",\n    \"Link to DeepL\": \"Deepl 在线翻译链接\",\n    \"List loaded embeddings\": \"获取嵌入式模型列表\",\n    \"List of active tabs (separated by commas). Available options are txt2img, img2img, txt2img-grids, img2img-grids, Extras, Favorites, Others. Custom folders are also supported by specifying their path.\": \"激活的图像保存目录标签 (用逗号分隔). 可用的标签有, 文生图(txt2img),图生图(img2img), 文生图-网格(txt2img-grids), 图生图-网格(img2img-grids), 后期处理(Extras), 收藏夹(Favorites), 其它(Others). 也可以通过指定文件目录来自定义目录标签.\",\n    \"List of model names (with file extension) or their hashes to use as black/whitelist, separated by commas.\": \"用于黑/白名单的模型名称（带文件扩展名）或其哈希值的列表，用逗号分隔\",\n    \"List of prompt inputs\": \"提示词输入列表\",\n    \"List of setting names, separated by commas, for settings that should go to the quick access bar at the top, rather than the usual setting tab. See modules/shared.py for setting names. Requires restarting to apply.\": \"设置项名称的列表，以英文逗号分隔，该设置会移动到顶部的快速访问栏，而不是默认的设置选项卡。有关设置名称，请参阅 modules/shared.py。(需保存设置并重启)\",\n    \"Live preview display period\": \"实时预览显示周期\",\n    \"Live preview file format\": \"实时预览文件格式\",\n    \"Live preview method\": \"实时预览模式\",\n    \"Live previews\": \"实时过程预览\",\n    \"Live preview subject\": \"实时预览主体\",\n    \"⚙️ Load\": \"⚙️ 加载\",\n    \"Load\": \"加载\",\n    \"Load All Settings\": \"载入所有设置\",\n    \"Load an image.\": \"加载一张图片\",\n    \"Load BG\": \"加载背景图\",\n    \"Load from:\": \"加载扩展列表\",\n    \"Load from JSON\": \"加载 JSON\",\n    \"Load from subdirectories\": \"从子目录中加载\",\n    \"load_history\": \"加载历史记录\",\n    \"Loading...\": \"载入中...\",\n    \"Load models/files in hidden directories\": \"加载隐藏目录中的模型/文件\",\n    \"Load models using stream loading method\": \"使用流式模型加载方法\",\n    \"Load Params\": \"载入参数\",\n    \"Load Preset\": \"加载预设\",\n    \"Load results\": \"加载结果\",\n    \"Load Scene\": \"加载场景\",\n    \"Load Settings\": \"载入设定\",\n    \"Load Video Settings\": \"载入视频设置\",\n    \"Local directory name\": \"本地目录名\",\n    \"localization\": \"本地化\",\n    \"Localization\": \"本地化\",\n    \"Localization file (Please leave `User interface` - `Localization` as None)\": \"本地化文件 (请将\\\"用户界面\\\" - “本地化翻译”选项设置为“无”)\",\n    \"Localization (requires restart)\": \"本地化翻译（需要重启）\",\n    \"Location\": \"FFmpeg 所在位置\",\n    \"Log\": \"日志\",\n    \"Log directory\": \"日志目录\",\n    \"Logo\": \"图标\",\n    \"Loop\": \"循环\",\n    \"Loopback\": \"回送\",\n    \"[Loopback] Automatically send generated images to this ControlNet unit\": \"[回送] 自动将生成后的图像发送到此 ControlNet 单元\",\n    \"Loopback option\": \"回送选项\",\n    \"Loopback source\": \"回送源\",\n    \"Looping recommendations:\": \"循环设置建议：\",\n    \"Loops\": \"回送次数\",\n    \"LoRA Block Weight\": \"LoRA Block Weight (LoRA 区块权重配置)\",\n    \"LoRA directory (if not default)\": \"LoRA 模型文件目录 (如非默认)\",\n    \"LoRA model name filter\": \"按名称过滤低秩微调 (LoRA) 模型\",\n    \"Lora: use old method that takes longer when you have multiple Loras active and produces same results as kohya-ss/sd-webui-additional-networks extension\": \"Lora: 使用旧的加载方法，当多个 Lora 激活时需要更长的时间，并且可以生成与 kohya-ss/sd-webui-additional-networks 扩展相同的结果\",\n    \"low contrast\": \"low contrast (低对比度)\",\n    \"Low fps\": \"低帧率\",\n    \"(Low values = visible seam)\": \"(数值越低=接缝越明显)\",\n    \"Low VRAM\": \"低显存模式\",\n    \"Low VRAM (8GB or below)\": \"低显存 (8 GB 以下) 模式\",\n    \"luminism\": \"luminism (光色派)\",\n    \"M00\": \"中间层\",\n    \"M_A_00\": \"模型 A 中间层\",\n    \"Made by\": \"制作方: \",\n    \"Made by deforum.github.io, port for AUTOMATIC1111's webui maintained by kabachuha\": \"由 deforum.github.io 制作，AUTOMATIC1111 的 webui 移植版本由 kabachuha 维护\",\n    \"magical realism\": \"magical realism (魔幻现实主义)\",\n    \"Main\": \"主菜单\",\n    \"Main menu position\": \"主菜单位置\",\n    \"Main Settings\": \"主设置\",\n    \"Maintenance\": \"维护\",\n    \"Make a backup copy of the model being edited when saving its metadata.\": \"保存元数据时，备份当前编辑的模型文件\",\n    \"Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution\": \"尝试生成与同一种子在特定分辨率下产生的图片相似的图片\",\n    \"Make GIF\": \"制作 GIF\",\n    \"Make Hires. fix+ run before any other extensions (will reload WebUI)\": \"使 高分辨率修复PLUS 在其它所有插件前执行 (勾选后会立刻重载WebUI)\",\n    \"Make Images\": \"制作图像\",\n    \"Make K-diffusion samplers produce same images in a batch as when making a single image\": \"使 K-diffusion 采样器在批量生成与生成单个图像时，产出相同的结果\",\n    \"Make LoRA (A-B)\": \"制作差分 LoRA (A-B)\",\n    \"Make LoRA (alpha * A - beta * B)\": \"制作差分 LoRA (α × A - β × B)\",\n    \"Make your changes, press 'View changes' to review the changed default values,\": \"修改后通过点击 '查看更改' 来复查修改后的默认设置数值。\\n然后点击 \\\"应用\\\" 把更改后的数值写入到 webui 根目录中的  ui-config.json文件中。\",\n    \"Make your choices, adjust your settings, set a name, save. To edit a prior choice, select from dropdown and overwrite.\": \"做出选择，调整设置，设置名称，保存。要编辑先前的选择，请从下拉列表中选择并覆盖。\",\n    \"Make Zip when Save?\": \"保存时创建 zip 压缩文件?\",\n    \"Manage Extensions\": \"管理扩展\",\n    \"manga\": \"manga (日漫)\",\n    \"manipulations\": \"图片处理\",\n    \"Manual install\": \"手动安装\",\n    \"mask\": \"蒙版\",\n    \"Mask\": \"蒙版\",\n    \"Mask blur\": \"蒙版边缘模糊度\",\n    \"Mask Blur Kernel Size\": \"蒙版模糊内核大小\",\n    \"Mask Blur Kernel Size(GaussianBlur)\": \"蒙版模糊内核大小（高斯模糊）\",\n    \"Mask Blur Kernel Size(MedianBlur)\": \"蒙版模糊内核大小（中值模糊）\",\n    \"Mask brightness adjust\": \"蒙版亮度调整\",\n    \"Mask by Category\": \"按分类创建蒙版\",\n    \"mask content ratio\": \"蒙版内容比例\",\n    \"Mask contrast adjust\": \"蒙版对比度调整\",\n    \"Mask directory\": \"遮罩图像目录\",\n    \"Masked content\": \"蒙版区域内容处理\",\n    \"Mask erosion (-) / dilation (+)\": \"蒙版图像腐蚀 (-) / 蒙版图像膨胀 (+)\",\n    \"Mask erosion (-) / dilation (+) 2nd\": \"蒙版图像腐蚀 (-) / 蒙版图像膨胀 (+)\",\n    \"Mask erosion (-) / dilation (+) 3rd\": \"蒙版图像腐蚀 (-) / 蒙版图像膨胀 (+)\",\n    \"Mask erosion (-) / dilation (+) 4th\": \"蒙版图像腐蚀 (-) / 蒙版图像膨胀 (+)\",\n    \"Mask erosion (-) / dilation (+) 5th\": \"蒙版图像腐蚀 (-) / 蒙版图像膨胀 (+)\",\n    \"Mask file\": \"蒙版文件\",\n    \"Mask fill\": \"蒙版填充\",\n    \"Mask for ControlNet Inpaint\": \"用于 ControlNet 重绘的蒙版\",\n    \"mask image:\": \"蒙版图像：\",\n    \"Masking Method\": \"蒙版方式\",\n    \"Mask max area ratio\": \"蒙版区域最大比率\",\n    \"Mask max area ratio 2nd\": \"蒙版区域最大比率\",\n    \"Mask max area ratio 3rd\": \"蒙版区域最大比率\",\n    \"Mask max area ratio 4th\": \"蒙版区域最大比率\",\n    \"Mask max area ratio 5th\": \"蒙版区域最大比率\",\n    \"Mask merge mode\": \"蒙版合并模式\",\n    \"Mask merge mode 2nd\": \"蒙版合并模式\",\n    \"Mask merge mode 3rd\": \"蒙版合并模式\",\n    \"Mask merge mode 4th\": \"蒙版合并模式\",\n    \"Mask merge mode 5th\": \"蒙版合并模式\",\n    \"Mask min area ratio\": \"蒙版区域最小比率\",\n    \"Mask min area ratio 2nd\": \"蒙版区域最小比率\",\n    \"Mask min area ratio 3rd\": \"蒙版区域最小比率\",\n    \"Mask min area ratio 4th\": \"蒙版区域最小比率\",\n    \"Mask min area ratio 5th\": \"蒙版区域最小比率\",\n    \"Mask mode\": \"蒙版模式\",\n    \"Mask Mode\": \"蒙版模式\",\n    \"Mask Mode(Override img2img Mask mode)\": \"蒙版模式（覆盖图生图的蒙版模式）\",\n    \"Mask option\": \"蒙版选项\",\n    \"Mask overlay blur\": \"蒙版覆盖模糊度\",\n    \"Mask Preprocessing\": \"蒙版处理\",\n    \"Mask schedule\": \"蒙版参数表\",\n    \"Mask Setting\": \"蒙版设置\",\n    \"masks from files: in [], like [mask1.png]\": \"从文件中获取蒙版:[] ，比如 [mask1.png]\",\n    \"Mask size\": \"蒙版尺寸\",\n    \"Mask source\": \"蒙版来源\",\n    \"Mask Target (e.g., girl, cats)\": \"蒙版目标（如 girl, cats）\",\n    \"Mask Threshold\": \"蒙版阈值\",\n    \"Mask transparency\": \"蒙版透明度\",\n    \"Mask x(→) offset\": \"蒙版 X 轴 (→) 偏移\",\n    \"Mask x(→) offset 2nd\": \"蒙版 X 轴 (→) 偏移\",\n    \"Mask x(→) offset 3rd\": \"蒙版 X 轴 (→) 偏移\",\n    \"Mask x(→) offset 4th\": \"蒙版 X 轴 (→) 偏移\",\n    \"Mask x(→) offset 5th\": \"蒙版 X 轴 (→) 偏移\",\n    \"Mask y(↑) offset\": \"蒙版 Y 轴 (↑) 偏移\",\n    \"Mask y(↑) offset 2nd\": \"蒙版 Y 轴 (↑) 偏移\",\n    \"Mask y(↑) offset 3rd\": \"蒙版 Y 轴 (↑) 偏移\",\n    \"Mask y(↑) offset 4th\": \"蒙版 Y 轴 (↑) 偏移\",\n    \"Mask y(↑) offset 5th\": \"蒙版 Y 轴 (↑) 偏移\",\n    \"Match input size\": \"匹配输入图尺寸\",\n    \"Max\": \"最大值\",\n    \"Max Crop Size\": \"最大修复尺寸\",\n    \"max frames\": \"最大帧数\",\n    \"Max frames\": \"最大帧数\",\n    \"Max Image Size\": \"最大图像尺寸\",\n    \"Maximize area\": \"最大化面积\",\n    \"Maximum aesthetic_score\": \"最大美学评分\",\n    \"Maximum batch size\": \"最大单批数量\",\n    \"Maximum execution time (seconds)\": \"最大执行时间(以秒为单位)\",\n    \"Maximum height\": \"最大高度\",\n    \"Maximum Image Height:\": \"图片最大高度\",\n    \"Maximum image size\": \"最大图像尺寸\",\n    \"Maximum image size, in megapixels\": \"上述选项的最大图像尺寸，单位：百万像素\",\n    \"Maximum Image Width:\": \"图片最大宽度：\",\n    \"Maximum Image Width/Height:\": \"图片最大宽度/高度：\",\n    \"Maximum keyframe gap\": \"最大关键帧间隔\",\n    \"Maximum number of faces to detect\": \"检测的最大人脸数量\",\n    \"Maximum number of images in upscaling cache\": \"图像放大缓存中的最大图片数量\",\n    \"Maximum prompt token count\": \"最大提示词词元长度\",\n    \"Maximum ranking\": \"最高评分\",\n    \"Maximum results\": \"候选Tag最大数量\",\n    \"Maximum score\": \"最高评分\",\n    \"Maximum width\": \"最大宽度\",\n    \"Max key frames\": \"最大关键帧数\",\n    \"Max models\": \"最大模型数量\",\n    \"Max number of dataset folders to show\": \"要显示的最大数据集文件夹数\",\n    \"Max number of top tags to show\": \"要显示的最大常见标签数\",\n    \"Max prompt words for [prompt_words] pattern\": \"用于替代 [prompt_words] 占位符的最大提示词数量\",\n    \"Max resolution of temporary files\": \"临时文件最大分辨率\",\n    \"Max steps\": \"最大步数\",\n    \"Max Token Length\": \"最大词元长度\",\n    \"M_B_00\": \"模型 B 中间层\",\n    \"MBW\": \"分块设置权重(MBW)\",\n    \"MBW Each\": \"A/B 模型分别分块设置权重 (MBW Each)\",\n    \"mbw weights\": \"分块权重\",\n    \"mediapipe_face\": \"mediapipe_face (脸部边缘检测)\",\n    \"melanin\": \"melanin (黑色素/黑人)\",\n    \"Memory\": \"内存\",\n    \"Memory optimization\": \"显存优化选项\",\n    \"Memory usage\": \"内存使用量\",\n    \"Merge\": \"合并\",\n    \"Merge!\": \"融合\",\n    \"Merge and gen\": \"融合并生成\",\n    \"Merge And Gen\": \"融合并生成\",\n    \"Merge and Invert\": \"合并且反相\",\n    \"Merge Block Weighted\": \"模型分块合并\",\n    \"Merge&Gen\": \"融合并生成\",\n    \"Merge LoRAs\": \"合并 LoRA\",\n    \"Merge mode\": \"合并模式\",\n    \"Merge Mode\": \"融合算法\",\n    \"Merge models and load it for generation\": \"融合模型并生成图片\",\n    \"Merge to Checkpoint\": \"合并到大模型\",\n    \"Message\": \"信息\",\n    \"messy\": \"messy (混乱)\",\n    \"Metadata to show in XY-Grid label for Model axes, comma-separated (example: \\\"ss_learning_rate, ss_num_epochs\\\")\": \"显示在 X/Y 表标签下的元数据选项，以逗号分隔（示例：\\\"ss_learning_rate, ss_num_epochs\\\"）\",\n    \"Method\": \"方案\",\n    \"MiDaS weight (vid2depth)\": \"MiDaS 权重 (vid2depth)\",\n    \"Min\": \"最小值\",\n    \"Minimize error\": \"最小错误阈值\",\n    \"minimum aesthetic_score\": \"按美学评分下限过滤\",\n    \"Minimum aesthetic_score\": \"最小美学评分\",\n    \"Minimum batch size\": \"最小单批数量\",\n    \"Minimum height\": \"最小高度\",\n    \"Minimum keyframe gap\": \"最小关键帧间隔\",\n    \"Minimum lighting ratio\": \"最小照明比率\",\n    \"Minimum number of pages per load\": \"每次加载的最小页数\",\n    \"Minimum prompt token count\": \"最小提示词词元长度\",\n    \"Minimum ranking\": \"最低评分\",\n    \"Minimum score\": \"最低评分\",\n    \"Minimum steps\": \"最小迭代步数\",\n    \"Minimum width\": \"最小宽度\",\n    \"min_mask_region_area\": \"最小蒙版面积\",\n    \"Min-max\": \"最低 - 最高\",\n    \"Mirror webcam\": \"镜像网络摄像头\",\n    \"missing metadata\": \" 无元数据\",\n    \"Mixed\": \"混合\",\n    \"Mixed Precision\": \"混合精度\",\n    \"MLDanbooru Tagger\": \"ML-Danbooru 标签器\",\n    \"mlsd\": \"mlsd (M-LSD 直线线条检测)\",\n    \"MLSD\": \"MLSD (直线)\",\n    \"mode\": \"模式\",\n    \"Mode\": \"模式\",\n    \"model\": \"模型\",\n    \"Model\": \"模型\",\n    \"Model 1\": \"模型 1\",\n    \"Model 2\": \"模型 2\",\n    \"Model 3\": \"模型 3\",\n    \"Model 4\": \"模型 4\",\n    \"Model 5\": \"模型 5\",\n    \"model A\": \"模型 A\",\n    \"model_A\": \"模型 A\",\n    \"Model A\": \"模型 A\",\n    \"Model_A\": \"模型A\",\n    \"model B\": \"模型 B\",\n    \"model_B\": \"模型 B\",\n    \"Model B\": \"模型 B\",\n    \"Model_B\": \"模型 B\",\n    \"model C\": \"模型 C\",\n    \"Model C\": \"模型 C\",\n    \"Model cache size (requires restart)\": \"模型缓存数量 (需重启)\",\n    \"Model compile mode (experimental)\": \"模型编译模式（实验性）\",\n    \"Model Converter\": \"模型转换\",\n    \"Model description/readme/notes/instructions\": \"模型的描述信息/说明/注释/指引\",\n    \"model hash\": \"模型哈希值\",\n    \"Model hash\": \"模型哈希值\",\n    \"Model Name\": \"模型名称\",\n    \"model of the upscaler to use. 'realesr-animevideov3' is much faster but yields smoother, less detailed results. the other models only do x4\": \"需要使用的超分模型。 'realesr-animevideov3'  速度更快但生成的结果更平滑、更详细。其他超分模型只支持 4 倍放大\",\n    \"Model path\": \"模型路径\",\n    \"Model Path\": \"模型路径\",\n    \"Model path filter\": \"按模型路径过滤\",\n    \"models\": \"模型相关\",\n    \"Models\": \"模型\",\n    \"Models...\": \"模型列表...\",\n    \"Model Toolkit\": \"模型工具箱\",\n    \"model to use\": \"使用的模型\",\n    \"Model Type\": \"模型种类\",\n    \"Model Types\": \"模型种类\",\n    \"Model Version\": \"模型版本\",\n    \"Mode to add the extra tags to the main tag list\": \"选择将额外标签添加到主要标签列表的模式\",\n    \"Mode to use for model list\": \"模型列表模式\",\n    \"Modules\": \"模块\",\n    \"monochromatic\": \"monochromatic (单色调)\",\n    \"More info about Anti Burn\": \"关于 Anti Burn 的更多信息\",\n    \"Motion\": \"运动参数\",\n    \"Mov2Mov output path for image\": \"Mov2Mov 图片输出路径\",\n    \"Mov2Mov output path for vedio\": \"Mov2Mov 视频输出路径\",\n    \"Mov2Mov output path for video\": \"Mov2Mov 视频输出路径\",\n    \"Move buttons copy instead of move\": \"将图库浏览器内所有 \\\"移动\\\" 按钮改为 \\\"复制\\\" 按钮\",\n    \"Move completion popup together with text cursor\": \"将弹出窗口与文本光标一起移动\",\n    \"Move ControlNet images to CPU (if applicable)\": \"将 ControlNet 图像移动到 CPU (如果适用)\",\n    \"Move ControlNet tensor to CPU (if applicable)\": \"将 ControlNet tensor 移至CPU (如果适用)\",\n    \"Move/Copy/Delete matching .txt files\": \"将图片的移动、复制、删除操作应用到与之同名的 txt 文件\",\n    \"Move face restoration model from VRAM into RAM after processing\": \"处理完成后，将面部修复模型从显存卸载到内存\",\n    \"Move File(s)\": \"移动文件\",\n    \"Move Mode (X key)\": \"移动模式(X 键)\",\n    \"Move or Delete\": \"移动或删除\",\n    \"Move quicksettings to image setting panel\": \"移动快速设置到左侧图像设置面板\",\n    \"Move to favorites\": \"　移动到收藏夹\",\n    \"Move VAE and CLIP to RAM when training hypernetwork. Saves VRAM.\": \"训练超网络时将 VAE 和 CLIP 模型移动到内存，可节省显存\",\n    \"Move VAE and CLIP to RAM when training if possible\": \"训练时尽可能将 VAE 与 CLIP 模型移动到内存\",\n    \"Move VAE and CLIP to RAM when training if possible. Saves VRAM.\": \"如果可行，训练时将 VAE 和 CLIP 模型从显存移动到内存，可节省显存\",\n    \"Move VAE to GPU\": \"将 VAE 移动到 GPU\",\n    \"Move VAE to GPU (if possible)\": \"将 VAE 移动到 GPU (如果允许)\",\n    \"Moving the canvas\": \"移动画布\",\n    \"Multi ControlNet: Max models amount (requires restart)\": \"ControlNet Unit 的最大数量 (需重启)\",\n    \"Multi-frame rendering\": \"多帧渲染\",\n    \"Multi Merge\": \"多重合并\",\n    \"Multi Model Merge\": \"多模型合并\",\n    \"Multiplication (2^N)\": \"倍率 (2^N)\",\n    \"multiplier\": \"倍率\",\n    \"Multiplier\": \"倍率\",\n    \"Multiplier for extra networks\": \"扩展模型默认权重\",\n    \"Multiplier (M) - set to 0 to get model A\": \"融合比例 (M) - 设为 0 等价于直接输出模型 A\",\n    \"multiply\": \"乘积\",\n    \"Multi Proc Cmd\": \"多进程命令\",\n    \"(must be < sampling steps)\": \"(需小于迭代步数)\",\n    \"My prompt is more important\": \"更偏向提示词\",\n    \"naive\": \"朴素卷积算法\",\n    \"naive_interpolating\": \"朴素插值算法\",\n    \"name\": \"名称\",\n    \"Name\": \"名称\",\n    \"Name 0\": \"名称 0\",\n    \"Name 1\": \"名称 1\",\n    \"Name 10\": \"名称 10\",\n    \"Name 11\": \"名称 11\",\n    \"Name 12\": \"名称 12\",\n    \"Name 13\": \"名称 13\",\n    \"Name 14\": \"名称 14\",\n    \"Name 15\": \"名称 15\",\n    \"Name 2\": \"名称 2\",\n    \"Name 3\": \"名称 3\",\n    \"Name 4\": \"名称 4\",\n    \"Name 5\": \"名称 5\",\n    \"Name 6\": \"名称 6\",\n    \"Name 7\": \"名称 7\",\n    \"Name 8\": \"名称 8\",\n    \"Name 9\": \"名称 9\",\n    \"nature\": \"nature (自然主义)\",\n    \"Navigate image viewer with gamepad\": \"使用游戏手柄导航图像查看器\",\n    \"Near clip\": \"近端衰减\",\n    \"need input your want to translate\": \"请输入你想翻译的内容\",\n    \"negative\": \"反向\",\n    \"Negative Guidance minimum sigma\": \"反向提示词引导最小 sigma\",\n    \"Negative prompt\": \"反向提示词\",\n    \"Negative Prompt\": \"反向提示词\",\n    \"Negative prompt for hires fix pass.\\nLeave empty to use the same negative prompt as in first pass.\": \"用于高分修复层的反向提示词\\n留空以使用与第一层相同的提示词\",\n    \"Negative prompt (press Ctrl+Enter or Alt+Enter to generate)\": \"反向提示词 (按 Ctrl+Enter 或 Alt+Enter 开始生成)\\nNegative prompt\",\n    \"Negative Prompts\": \"反向提示词\",\n    \"negative prompt to be appended to *all* prompts. DON'T use --neg here!\": \"反向提示词会被添加到左右提示词内，请勿在此处使用 --neg 字段\",\n    \"Negative Prompt Weight\": \"反向提示词权重\",\n    \"Negative Prompt, will also be appended\": \"追加反向提示词\",\n    \"Net height\": \"深度图高度\",\n    \"Net width\": \"深度图宽度\",\n    \"Network module\": \"附加网络模块\",\n    \"Network module 1\": \"附加模型 1\",\n    \"Network module 2\": \"附加模型 2\",\n    \"Network module 3\": \"附加模型 3\",\n    \"Network module 4\": \"附加模型 4\",\n    \"Network module 5\": \"附加模型 5\",\n    \"Never\": \"从不\",\n    \"Nevysha Cozy Nest Settings\": \"Nevysha Cozy Nest 设置\",\n    \"Nevysha Cozy Nest Update Info\": \"Nevysha Cozy Nest 更新信息\",\n    \"New Canvas Height\": \"新画布高度\",\n    \"New Canvas Width\": \"新画布宽度\",\n    \"New defaults will apply after you restart the UI.\": \"新的默认设置将会在重启 UI 后应用。\",\n    \"newest first\": \"按发布日期倒序\",\n    \"New preset name \": \"新预设名称\",\n    \"New Scribble Drawing Height\": \"新线稿画板高度\",\n    \"New Scribble Drawing Width\": \"新线稿画板宽度\",\n    \"Next batch\": \"下一批\",\n    \"Next Page\": \"下一页\",\n    \"no\": \"否\",\n    \"No\": \"否\",\n    \"no-ema\": \"删除 EMA 权重\",\n    \"no find:\": \"未找到：\",\n    \"no image selected\": \"没有图片被选中\",\n    \"No interpolation\": \"原样输出\",\n    \"No interpolation will be used. Requires one model; A. Allows for format conversion and VAE baking.\": \"直接输出主要模型。需要一个模型 A。可用于模型格式转换和嵌入 VAE。\",\n    \"Noise\": \"噪声\",\n    \"Noise Inversion\": \"噪声反转\",\n    \"Noise mask schedule\": \"噪点蒙版参数表\",\n    \"(noise multiplier; applies to Euler a and other samplers that have a in them)\": \"(噪声倍数: 适用于 Euler a 和其它具有 a 的采样方法)\",\n    \"Noise multiplier for img2img\": \"图生图噪声倍率\",\n    \"(noise multiplier; higher = more unperdictable results)\": \"(噪声倍数: 越高=结果越难以预测)\",\n    \"Noise multiplier schedule\": \"噪声乘法调度（Noise multiplier schedule）\",\n    \"Noise schedule\": \"噪点值表\",\n    \"Noise Tolerance\": \"噪声容忍度\",\n    \"Noise type\": \"噪声类型\",\n    \"No model has new version\": \"所有模型均是最新版本\",\n    \"none\": \"无\",\n    \"None\": \"无\",\n    \"NONE\": \"无\",\n    \"None (just grayscale)\": \"什么都不做（灰度模式）\",\n    \"None - prompt only\": \"无 - 仅提示词\",\n    \"normal\": \"正常\",\n    \"Normal\": \"常规\",\n    \"normal_bae\": \"normal_bae (Bae 法线贴图提取)\",\n    \"Normally, it creates a single random prompt. With prompt compounder, it will generate multiple prompts and compound them together.\": \"一般情况下只能创建一个单一的随机提示。但有了提示词混合，可以生成多个提示词并将它们复合在一起。\",\n    \"(normally you'd do less with less denoising)\": \"(正常情况下越小的重绘幅度需要的迭代步数更少)\",\n    \"normal_midas\": \"normal_midas (Midas 法线贴图提取)\",\n    \"Normal with batch\": \"正常（带批处理）\",\n    \"not\": \"不会\",\n    \"Note that parseq overrides:\": \"以下参数将会被参数定序器覆盖设置：\",\n    \"(not for Video Input mode)\": \" (不用于视频输入模式)\",\n    \"Nothing here. Add some content to the following directories:\": \"暂无内容。请添加模型到以下目录：\",\n    \"nudity\": \"nudity (裸体)\",\n    \"NUl Image Enhancer\": \"NUI 图像增强\",\n    \"Number of columns on the page\": \"每页列数\",\n    \"Number of frames\": \"总帧数\",\n    \"Number of iterations\": \"迭代次数\",\n    \"Number of negative vectors per token\": \"每个词元的反向向量数\",\n    \"Number of repeats for a single input image per epoch; used only for displaying epoch number\": \"每期 (epoch) 中单个输入图像的重复次数； 仅用于显示期数\",\n    \"Number of rows on the page\": \"每页行数\",\n    \"Number of samples to generate\": \"要生成的样本数量\",\n    \"Number of Samples to Generate\": \"要生成的样本数量\",\n    \"Number of sampling steps for upscaled picture. If 0, uses same as for original.\": \"高分辨率修复图片的迭代步数。如果为0，则使用与文生图设置相同的迭代步数。\",\n    \"number of the frames that we will blend between current imagined image and input frame image\": \"当前想象图像和输入帧图像之间混合的帧数\",\n    \"Number of vectors per token\": \"每个词元的向量数\",\n    \"(O10) Output ckpt Name\": \"(O10) 输出模型文件名\",\n    \"(O1) Output ckpt Name\": \"(O1) 输出模型文件名\",\n    \"(O2) Output ckpt Name\": \"(O2) 输出模型文件名\",\n    \"(O3) Output ckpt Name\": \"(O3) 输出模型文件名\",\n    \"(O4) Output ckpt Name\": \"(O4) 输出模型文件名\",\n    \"(O5) Output ckpt Name\": \"(O5) 输出模型文件名\",\n    \"(O6) Output ckpt Name\": \"(O6) 输出模型文件名\",\n    \"(O7) Output ckpt Name\": \"(O7) 输出模型文件名\",\n    \"(O8) Output ckpt Name\": \"(O8) 输出模型文件名\",\n    \"(O9) Output ckpt Name\": \"(O9) 输出模型文件名\",\n    \"object\": \"object (物件)\",\n    \"object - Can be a random object, a building or a vehicle.\": \"object - 物件 - 可以是一个随机的物体，也可以是一个建筑物或一辆车。\",\n    \"octane render\": \"octane render (OC渲染)\",\n    \"official Deforum Discord\": \" Deforum 官方 Discord 频道\",\n    \"Official Deforum Wiki:\": \"Deforum 官方 Wiki: \",\n    \"# of threads to use for hash calculation (increase if using an SSD)\": \"用于哈希计算的线程数 (如果使用 SSD 可适当增加)\",\n    \"oldest first\": \"按发布日期正序\",\n    \"Once turned on, it will retry for n amount of times to get an image with the quality score. If not, it will take the best image so far and continue.\": \"一旦启用，它将持续生成 N 次以获得具有一定质量分数的图像。如果没有，它将保留评分最好的图像持续生成。\",\n    \"One Button Prompt\": \"One Button Prompt (一键生成提示词)\",\n    \"One Button Run and Upscale\": \"一键运行并放大\",\n    \"online\": \"线上服务\",\n    \"Online 3D Openpose Editor\": \"在线 3D Openpose 编辑器\",\n    \"(only applies if non-zero and overrides above)\": \"(仅在数值设置为非零时启用, 启用时覆盖原 Token 合并比率设置)\",\n    \"Only applies to inpainting models. Determines how strongly to mask off the original image for inpainting and img2img. 1.0 means fully masked, which is the default behaviour. 0.0 means a fully unmasked conditioning. Lower values will help preserve the overall composition of the image, but will struggle with large changes.\": \"仅适用于局部重绘专用的模型（模型后缀为 inpainting.ckpt 的模型）。决定了蒙版在局部重绘以及图生图中屏蔽原图内容的强度。 1.0 表示完全屏蔽原图，这是默认行为。0.0 表示完全不屏蔽让原图进行图像调节。较低的值将有助于保持原图的整体构图，但很难遇到较大的变化\",\n    \"Only copy to models with no metadata\": \"仅复制到不含元数据的模型\",\n    \"Only copy to models with same session ID\": \"仅复制到具有相同 Session ID 的模型\",\n    \"Only Hand\": \"仅显示手部(移除脚部)\",\n    \"*Only in use with pix2pix checkpoints!*\": \"*仅在加载 Pix2Pix 模型时生效!*\",\n    \"Only masked\": \"仅蒙版区域\",\n    \"Only masked padding, pixels\": \"仅蒙版区域下边缘预留像素\",\n    \"only other types --> Will pick only from the more unique types, such as stained glass window or a funko pop\": \"only other types -- 仅其它类型 --> 只从其它更独特的类型中挑选，如彩色玻璃窗或一只玩具人偶。\",\n    \"Only show alias\": \"仅展示别名\",\n    \"Only Show Models have no Info\": \"只显示缺少信息的模型\",\n    \"Only show models that have/don't have user-added metadata\": \"按是否有元数据过滤模型\",\n    \"Only show .safetensors format models\": \"只显示 .safetensors 格式的模型\",\n    \"Only store preferences locally\": \"仅在本地保存设置\",\n    \"Only upscale will not use txt2img to generate an image.\": \"仅放大时不会通过文生图功能生成图像\",\n    \"Only use mid-control when inference\": \"仅在生成图片时使用中间层控制 (mid-control)\",\n    \"Onnx model filename\": \"Onnx 模型文件名 (包含路径)\",\n    \"ONNX opset version\": \"ONNX 算子集版本\",\n    \"(O)Output Model Name\": \"输出模型文件名\",\n    \"Opacity\": \"不透明度\",\n    \"Open...\": \"打开...\",\n    \"Open images output directory\": \"打开图像输出目录\",\n    \"Open intermediate results\": \"立即打开当前效果图\",\n    \"Open new canvas\": \"打开新画布\",\n    \"Open New Canvas\": \"打开新画布\",\n    \"Open New Scribble Drawing Canvas\": \"创建新的线稿画板\",\n    \"Open output directory\": \"打开输出目录\",\n    \"openpose\": \"openpose (OpenPose 姿态)\",\n    \"OpenPose\": \"OpenPose (姿态)\",\n    \"OpenPose Editor\": \"OpenPose 编辑器\",\n    \"openpose_face\": \"openpose_face (OpenPose 姿态及脸部)\",\n    \"openpose_faceonly\": \"openpose_faceonly (OpenPose 仅脸部)\",\n    \"openpose_full\": \"openpose_full (OpenPose 姿态、手部及脸部)\",\n    \"openpose_hand\": \"openpose_hand (OpenPose 姿态及手部)\",\n    \"Open results\": \"打开最终效果图\",\n    \"Open TextEditor\": \"打开文本编辑器\",\n    \"Open the generated .ebs under project directory and press [Run All] button.\": \"打开工程目录下生成的 .ebs 文件，按[Run All]按钮。\",\n    \"Open this model's civitai url\": \"在新标签页打开本模型的 Civitai 页面\",\n    \"Open Url At Client Side\": \"在浏览器侧打开链接\",\n    \"Optical Flow\": \"光流法\",\n    \"Optical flow cadence\": \"生成间隔中启用光流法\",\n    \"Optimizations\": \"优化设置\",\n    \"Options are all options hardcoded, and additional you added in additional_components.py\": \"选项都是硬编码的选项，并且是您在 additional_components.py 中添加的附加选项\",\n    \"Options in main UI\": \"主界面额外选项\",\n    \"- or -\": \"- 或 -\",\n    \"or\": \"或\",\n    \"Order\": \"排序\",\n    \"original\": \"原图\",\n    \"Original:\": \"原项目:\",\n    \": Original extension\": \": 原始扩展名\",\n    \": Original extension\\nAvailable algorithms:\": \": 原始扩展名\\n可用算法: \",\n    \": Original filename without extension\": \": 没有扩展名的原始文件名\",\n    \"Original filename without extension\": \"没有扩展名的原始文件名\",\n    \"Original file’s hash (good for deleting duplication)\": \"原始文件哈希值 (有助于检测重复项)\",\n    \"Original First\": \"原文在上\",\n    \"Original Image\": \"原始图像\",\n    \"OriginalImg\": \"OriginalImg (原始输入的第一帧)\",\n    \"Original Movie Path\": \"原始视频路径\",\n    \"Original negative prompt\": \"原始反向提示词\",\n    \"Original prompt\": \"原始正向提示词\",\n    \"original video frame\": \"原始视频帧\",\n    \"Original Weights\": \"原始权重\",\n    \"or, manually enhance the image\": \"↓手动控制图像增强参数↓\",\n    \"(or open as text in a new page)\": \"（或在新的标签页查看）\",\n    \"or to CTRL+SHIFT\": \"将 CTRL 绑定更改为 CTRL+SHIFT\",\n    \"Other\": \"其他\",\n    \"Other prompt fields\": \"其它提示词段\",\n    \"others\": \"其它\",\n    \"- Others\": \"- 其它\",\n    \"Others\": \"其它\",\n    \"Other Setting\": \"其他设置\",\n    \"OUT00\": \"输出层 00\",\n    \"OUT01\": \"输出层 01\",\n    \"OUT02\": \"输出层 02\",\n    \"OUT03\": \"输出层 03\",\n    \"OUT04\": \"输出层 04\",\n    \"OUT05\": \"输出层 05\",\n    \"OUT06\": \"输出层 06\",\n    \"OUT07\": \"输出层 07\",\n    \"OUT08\": \"输出层 08\",\n    \"OUT09\": \"输出层 09\",\n    \"OUT10\": \"输出层 10\",\n    \"OUT11\": \"输出层 11\",\n    \"OUT_A_00\": \"模型 A 输出层 00\",\n    \"OUT_A_01\": \"模型 A 输出层 01\",\n    \"OUT_A_02\": \"模型 A 输出层 02\",\n    \"OUT_A_03\": \"模型 A 输出层 03\",\n    \"OUT_A_04\": \"模型 A 输出层 04\",\n    \"OUT_A_05\": \"模型 A 输出层 05\",\n    \"OUT_A_06\": \"模型 A 输出层 06\",\n    \"OUT_A_07\": \"模型 A 输出层 07\",\n    \"OUT_A_08\": \"模型 A 输出层 08\",\n    \"OUT_A_09\": \"模型 A 输出层 09\",\n    \"OUT_A_10\": \"模型 A 输出层 10\",\n    \"OUT_A_11\": \"模型 A 输出层 11\",\n    \"OUT_B_00\": \"模型 B 输出层 00\",\n    \"OUT_B_01\": \"模型 B 输出层 01\",\n    \"OUT_B_02\": \"模型 B 输出层 02\",\n    \"OUT_B_03\": \"模型 B 输出层 03\",\n    \"OUT_B_04\": \"模型 B 输出层 04\",\n    \"OUT_B_05\": \"模型 B 输出层 05\",\n    \"OUT_B_06\": \"模型 B 输出层 06\",\n    \"OUT_B_07\": \"模型 B 输出层 07\",\n    \"OUT_B_08\": \"模型 B 输出层 08\",\n    \"OUT_B_09\": \"模型 B 输出层 09\",\n    \"OUT_B_10\": \"模型 B 输出层 10\",\n    \"OUT_B_11\": \"模型 B 输出层 11\",\n    \"Outpainting direction\": \"向外绘制的方向\",\n    \"output\": \"输出\",\n    \"Output\": \"输出\",\n    \"Output animation path\": \"动画输出路径\",\n    \"Output directory\": \"输出目录\",\n    \"Output Directory\": \"输出目录\",\n    \"Output directory for grids\": \"网格图输出文件夹\",\n    \"Output directory for grids; if empty, defaults to two directories below\": \"网格图统一输出文件夹； 如果为空，则按以下两个文件夹分别输出\",\n    \"Output directory for images from extras tab\": \"后期处理输出文件夹\",\n    \"Output directory for images; if empty, defaults to three directories below\": \"统一输出文件夹； 如果为空，则按以下三个文件夹分别输出\",\n    \"Output directory for img2img grids\": \"图生图网格输出文件夹\",\n    \"Output directory for img2img images\": \"图生图输出文件夹\",\n    \"Output directory for txt2img grids\": \"文生图网格输出文件夹\",\n    \"Output directory for txt2img images\": \"文生图输出文件夹\",\n    \": Output extension (has no dot)\": \"输出扩展名 (没有 '.' 点)\",\n    \"Output filename\": \"输出文件名\",\n    \"Output filename format\": \"输出文件名格式\",\n    \"Output filename formats\": \"输出文件名格式\",\n    \"Output format\": \"输出格式\",\n    \"output height resolution\": \"输出高度分辨率\",\n    \"Output Image Width\": \"输出图像宽度\",\n    \"Output Model Name\": \"输出模型文件名\",\n    \"Output name\": \"输出名称\",\n    \"Output path\": \"输出路径\",\n    \"Output Paths\": \"输出路径\",\n    \"Output per image:\": \"单独输出每张图像：\",\n    \"output resolution\": \"输出分辨率\",\n    \"outputs\": \"输出\",\n    \"Output settings: all settings (including fps and max frames)\": \"输出设置：所有设置（包括帧率和最大帧数）\",\n    \"Output type\": \"输出类型\",\n    \"output video resolution\": \"输出视频的分辨率\",\n    \"Out Res\": \"输出分辨率\",\n    \"overlay\": \"叠加\",\n    \"Overlay mask\": \"覆盖蒙版\",\n    \"override:\": \"覆盖以下参数：\",\n    \"Override\": \"覆盖\",\n    \"Override `Denoising strength` to 1?\": \"覆写 `重绘幅度` 为 1?\",\n    \"Override options (choose the related subject type first for better results)\": \"覆盖选项 (首选相关的主题类型以获得更好的结果)\",\n    \"Override `prompt` to the same value as `original prompt`?(and `negative prompt`)\": \"覆写 `提示词` 为 `初始提示词`?` (反向提示词` 同理)\",\n    \"Override `Sampling method` to Euler?(this method is built for it)\": \"覆写 `采样方法` 为 Euler? (这个方法就是为它设计的)\",\n    \"Override `Sampling Steps` to the same value as `Decode steps`?\": \"覆写 `采样迭代步数` 为 `解码迭代步数`?\",\n    \"Override settings\": \"覆盖设置\",\n    \"overwrite\": \"允许覆盖\",\n    \"Overwrite\": \"覆写\",\n    \"Overwrite extracted frames\": \"覆盖已有帧\",\n    \"Overwrite image size\": \"覆盖图像尺寸\",\n    \"Overwrite input frames\": \"覆盖输入帧\",\n    \"Overwrite Old Embedding\": \"覆盖同名嵌入式模型文件\",\n    \"Overwrite Old Hypernetwork\": \"覆盖同名超网络文件\",\n    \"Overwrite subject\": \"覆盖主题\",\n    \"Overwrite subject:\": \"覆盖主题:\",\n    \"Overwrite type of image:\": \"覆盖图像类型\",\n    \"Padding token (ID or single token)\": \"填充提示词(完整ID或者单个提示词)\",\n    \"Pad prompt/negative prompt to be same length\": \"补齐正向/反向提示词到相同长度\",\n    \"Pad Tokens\": \"词元填充\",\n    \"Page Index\": \"页码\",\n    \"painting\": \"painting (画作)\",\n    \"Panorama to 3D mesh\": \"全景图转 3D 网格\",\n    \"Parse!\": \"解析\",\n    \"Parseq\": \"参数定序器 (parameter sequencer)\",\n    \"Parseq does\": \"参数定序器将\",\n    \"Parseq Manifest (JSON or URL)\": \"参数定序器配置文件（JSON 或者链接）\",\n    \"Passing ControlNet parameters with \\\"Send to img2img\\\"\": \"使用\\\"发送到图生图\\\"时传输 ControlNet 参数\",\n    \"Paste available values into the field\": \"将可用值粘贴到字段中\",\n    \"path name\": \"路径名\",\n    \"Path relative to the webui folder\": \"相对于 webui 文件夹的路径\",\n    \"Paths for saving\": \"保存路径\",\n    \"Path to directory containing annotator model directories (requires restart, overrides corresponding command line flag)\": \"预处理器模型 (annotator model) 的文件路径 (需重启，以覆盖相应的命令行标志)\",\n    \"Path to directory where to write outputs\": \"进行输出的目录路径\",\n    \"Path to directory with input images\": \"带有输入图像的目录路径\",\n    \"/path/to/images or /path/to/images/**/*\": \"/path/to/images 或 /path/to/images/**/*\",\n    \"Path to settings file you want to load. Path can be relative to webui folder OR full - absolute\": \"需要加载的设置文件路径。该路径可以相对于 SD-WebUI 根目录，也可以是完整的绝对路径\",\n    \"Pause\": \"暂停\",\n    \"PBRemTools\": \"精确背景去除工具\",\n    \"performance\": \"性能\",\n    \"Perform warmup\": \"进行预热\",\n    \"per side\": \"每边数量\",\n    \"persistent cond cache\": \"持久化调整缓存\",\n    \"Perspective\": \"透视\",\n    \"Perspective Flip\": \"透视翻转\",\n    \"Perspective flip gamma\": \"透视翻转伽马值\",\n    \"Perspective flip phi\": \"透视翻转角度（垂直）\",\n    \"Perspective flip theta\": \"透视翻转角度（水平）\",\n    \"photograph\": \"photograph (照片)\",\n    \"photography\": \"photography (摄影)\",\n    \"Pick Subfolder and Model Version\": \"选择子目录与模型版本\",\n    \"pin_light\": \"点光\",\n    \"Pixelize\": \"像素化\",\n    \"Pixel Perfect\": \"完美像素模式\",\n    \"Pixels to expand\": \"拓展的像素数\",\n    \"Place options in main UI into an accordion\": \"将选项置入主界面的一个手风琴式的容器中\",\n    \"Place this at back of generated prompt (suffix)\": \"此框填写的提示词放在生成提示词的后面 (后缀)\",\n    \"Place this in front of generated prompt (prefix)\": \"此框填写的提示词放在生成提示词的前面 (前缀)\",\n    \"Platform\": \"运行平台\",\n    \"Please add text prompts to generate masks\": \"请添加文本提示词以生成蒙版\",\n    \"Please always keep values in math functions above 0.\": \"请始终保持数学函数中的值大于 0。\",\n    \"Please enable the following settings to use controlnet from this script.\": \"请启用以下设置，以保证可以在此脚本中调用ControlNet。\",\n    \"Please use smaller tile size when got CUDA error: out of memory.\": \"当出现 CUDA error: out of memory 时，使用更小的分块尺寸\",\n    \"Please use smaller tile size when see CUDA error: out of memory.\": \"当出现 CUDA error: out of memory 时，使用更小的尺寸大小\",\n    \"PNG info\": \"PNG 图片信息\",\n    \"PNG Info\": \"PNG 图片信息\",\n    \"PNGs\": \"图片（PNG格式）\",\n    \"point1 x\": \"X 轴点 1\",\n    \"point1 y\": \"Y 轴点 1\",\n    \"point2 x\": \"X 轴点 2\",\n    \"point2 y\": \"Y 轴点 2\",\n    \"point3 y\": \"Y 轴点 3\",\n    \"points_per_batch\": \"每批采样点\",\n    \"points_per_side\": \"每边采样点\",\n    \"polylines_sharp\": \"多边形算法 - 锐利\",\n    \"polylines_soft\": \"多边形算法 - 柔和\",\n    \"Pooling Avg\": \"池化平均值\",\n    \"Pooling Max\": \"池化最大值\",\n    \"pop art\": \"pop art (波普艺术)\",\n    \"popular\": \"popular (流行艺术)\",\n    \", port for AUTOMATIC1111's webui maintained by\": \", 是为 AUTOMATIC1111's webui 提供的插件项目，项目维护者: \",\n    \"portrait\": \"portrait (肖像)\",\n    \"Pose\": \"姿势\",\n    \"Position (center to edge)\": \"位置 (中心到边缘)\",\n    \"Position (left to right)\": \"位置 (从左到右)\",\n    \"Positions\": \"分区位置\",\n    \"positive\": \"正向\",\n    \"Positive / Negative Prompts\": \"正向 / 反向提示词\",\n    \"positive prompt to be appended to *all* prompts\": \"正向提示词会被添加到所有提示词中\",\n    \"Postprocessing\": \"后期处理\",\n    \"Post Processing\": \"后期处理\",\n    \"Post-Processing\": \"后处理\",\n    \"Postprocessing operation order\": \"后处理操作顺序\",\n    \"Precision\": \"精度\",\n    \"predicted_iou_threshold\": \"预测交并比阈值\",\n    \"pred_iou_thresh\": \"预测滤波阈值\",\n    \"Prefix\": \"前缀\",\n    \"prefix AND prompt + suffix\": \"prefix AND prompt + suffix (前缀 AND 提示词 + 后缀)\",\n    \"prefix + prefix + prompt + suffix\": \"prefix + prefix + prompt + suffix (前缀 + 前缀 + 提示词 + 后缀)\",\n    \"Preload images at startup for first tab\": \"在启动时为第一个选项卡预载图像\",\n    \"prepare ebsynth\": \"预处理 Ebsynth\",\n    \"prepend\": \"前置\",\n    \"Prepend\": \"添加到开头\",\n    \"Prepend additional tags\": \"将额外标签前置\",\n    \"Preprocess\": \"预处理\",\n    \"Preprocess images\": \"图像预处理\",\n    \"Pre-Processing\": \"预处理\",\n    \"Preprocessor\": \"预处理器\",\n    \"Preprocessor Preview\": \"预处理结果预览\",\n    \"Preprocessor resolution\": \"预处理器分辨率\",\n    \"Preprocessor Resolution\": \"预处理器分辨率\",\n    \"Prerequisites and Important Info:\": \"前提条件和重要信息：\",\n    \"Preset\": \"预设\",\n    \"Preset Manager\": \"预设管理器\",\n    \"Presets\": \"预设\",\n    \"Preset Weights\": \"预设权重\",\n    \"Preset_Weights\": \"预设权重\",\n    \"Prev batch\": \"上一批\",\n    \"Prevent empty spots in grid (when set to autodetect)\": \"自动检测并消除网格图中的空位\",\n    \"Preview annotator result\": \"预览预处理结果\",\n    \"Preview as Input\": \"预处理结果作为输入\",\n    \"Preview automatically when add/remove points\": \"添加/删除标记点时自动预览\",\n    \"Preview image negative prompt\": \"预览图反向提示词\",\n    \"Preview image prompt\": \"预览图提示词\",\n    \"Preview mask\": \"预览蒙版\",\n    \"Preview Segmentation\": \"预览分离结果\",\n    \"Preview segmentation image\": \"预览语义分割图像\",\n    \"Previous\": \"Previous (上一生成帧)\",\n    \"Prev Page\": \"上一页\",\n    \"Primary model (A)\": \"模型 A\",\n    \"primitivism\": \"primitivism (原始主义画派)\",\n    \"Print\": \"输出\",\n    \"Print all deviations\": \"输出所有偏移量\",\n    \"print change\": \"打印变更\",\n    \"Print debug logs to the console\": \"将调试日志输出到控制台\",\n    \"Print extra hypernetwork information to console.\": \"将额外的超网络 (hypernetwork) 信息输出到控制台\",\n    \"Print image deletion messages to the console\": \"打印图像删除信息到控制台\",\n    \"Print warning logs to the console\": \"将警告信息输出到控制台\",\n    \"Process given file(s) under the input folder, seperate by comma\": \"指定在输入文件夹中要处理图像的文件名 (使用逗号隔开)\",\n    \"Process images in a directory on the same machine where the server is running.\": \"处理服务器主机上某一目录里的图像\",\n    \"processing |\": \"处理中 |\",\n    \"Process Stage\": \"过程步骤\",\n    \"Produce an image that can be tiled.\": \"生成可用于平铺(tiled)的图像\",\n    \"Progressbar and preview update period\": \"进度条/预览图更新周期\",\n    \"Progressbar/preview update period, in milliseconds\": \"进度条/预览图更新周期 (毫秒)\",\n    \"Project directory\": \"工程目录\",\n    \"project setting\": \"工程设置\",\n    \"Prompt\": \"提示词\",\n    \"prompt 1\": \"提示词①\",\n    \"prompt 2\": \"提示词②\",\n    \"prompt 4\": \"提示词④\",\n    \"prompt 5\": \"提示词⑤\",\n    \"Prompt attention parser\": \"提示词注意力解析器\",\n    \"Prompt compounder\": \"提示词混合\",\n    \"Prompt fields\": \"提示词段\",\n    \"Prompt for face\": \"针对脸部的提示词\",\n    \"Prompt for Face\": \"脸部提示词\",\n    \"Prompt for hires fix pass.\\nLeave empty to use the same prompt as in first pass.\": \"用于高分修复层的正向提示词\\n留空以使用与第一层相同的提示词\",\n    \"prompting\": \"提示词相关\",\n    \"Prompt matrix\": \"提示词矩阵\",\n    \"Prompt (press Ctrl+Enter or Alt+Enter to generate)\": \"正向提示词 (按 Ctrl+Enter 或 Alt+Enter 开始生成)\\nPrompt\",\n    \"Prompts\": \"提示词\",\n    \"Prompts are stored in JSON format. If you've got an error, check it in a\": \"提示词以 JSON 格式存储。如果有错误，请在\",\n    \"Prompts are stored in JSON format. If you've got an error, check it in validator,\": \"提示词以 JSON 格式存储。如果您有错误，请在验证器中检查，\",\n    \"Prompt seperator\": \"提示词分隔符\",\n    \"Prompt seperator mode\": \"提示词分隔模式\",\n    \"prompts for your animation in a JSON format. Use --neg words to add 'words' as negative prompt\": \"动画的提示词以 JSON 格式储存。使用 --neg 字段去添加反向提示词\",\n    \"Prompts from file or textbox\": \"从文本框或文件载入提示词\",\n    \"Prompts negative\": \"反向提示词\",\n    \"Prompts positive\": \"正向提示词\",\n    \"Prompt template\": \"提示词模板\",\n    \"Prompt Translator\": \"提示词翻译器\",\n    \"Prompt, will append to your t2i prompt\": \"追加提示词\",\n    \"Prompt word wrap length limit\": \"提示词换组长度限制\",\n    \"Provider\": \"提供方\",\n    \"Proxy\": \"代理\",\n    \"Pruning Methods\": \"模型修剪\",\n    \"psychedelic\": \"psychedelic (迷幻艺术)\",\n    \"Put variable parts at start of prompt\": \"把可变部分放在提示词文本的开头\",\n    \"Put weight sets. float number x 25\": \"输入权重，共 25 个浮点数，逗号分隔\",\n    \"quad\": \"二阶\",\n    \"Quality\": \"质量\",\n    \"Quality for saved jpeg images\": \"保存 JPEG 图片的质量\",\n    \"Quality Gate\": \"质量把关\",\n    \"Quantize\": \"量化\",\n    \"query\": \"查询\",\n    \"queue:\": \"排队中: \",\n    \"Quick\": \"快速设置\",\n    \"Quick batch\": \"快速批处理\",\n    \"Quick Guide\": \"快速指引\",\n    \"Quick Save\": \"快速保存\",\n    \"Quicksettings list\": \"快捷设置列表\",\n    \"Quicksettings position\": \"快速设置位置\",\n    \"random\": \"随机\",\n    \"Randomness\": \"随机度\",\n    \"Random number generator source.\": \"随机数生成来源\",\n    \"Random number generator source. Changes seeds drastically. Use CPU to produce the same picture across different vidocard vendors.\": \"随机数的生成来源。大幅度改变种子。使用CPU来在不同型号显卡间产生相同的图像\",\n    \"range\": \"范围\",\n    \"Range\": \"范围\",\n    \"ranking\": \"评分\",\n    \"ranking filter\": \"按图片评分过滤\",\n    \"Ranking filter\": \"评分过滤器\",\n    \"rating\": \"评分\",\n    \"Rating\": \"评分\",\n    \"Rating confidents\": \"评级置信度\",\n    \"Read generation parameters from prompt or last generation if prompt is empty into user interface.\": \"从提示词或上次生成的图片中读取生成参数\",\n    \"read_last_image\": \"载入上次图像\",\n    \"read_last_settings\": \"载入上次设置\",\n    \"*READ ME before you use this mode!*\": \"请在使用前认真阅读\",\n    \"Read parameters (prompt, etc...) from txt2img tab when making previews\": \"进行预览时，从文生图选项卡中读取参数（提示词等）\",\n    \"Read tabular commands\": \"读取 tabular 命令\",\n    \"Read tags from text files\": \"从文本文件中读取提示词\",\n    \"realism\": \"realism (现实主义)\",\n    \"Reapply ranking after moving files\": \"移动文件后重新评分\",\n    \"Rebuild exif cache\": \"重建 EXIF 缓存\",\n    \"Recipe\": \"配方\",\n    \"recombine ebsynth\": \"重组 Ebsynth\",\n    \"Recommended settings: Sampling Steps: 80-100, Sampler: Euler a, Denoising strength: 0.8\": \"推荐设置: 采样迭代步数: 80-100, 采样器: Euler a, 重绘幅度: 0.8\",\n    \"Recommended to set tile sizes as large as possible before got CUDA error: out of memory.\": \"建议在得到 CUDA error: out of memory 报错前尽可能大的设置编码器分块大小\",\n    \"Recommend enabling the following settings.\": \"建议启用以下设置：\",\n    \"Reconstruct prompt from existing image and put it into the prompt field.\": \"从现有的图像中重构出提示词，并将其放入提示词的输入文本框\",\n    \"Rectangular\": \"矩形\",\n    \"red-cyan-anaglyph\": \"红蓝浮雕效果\",\n    \"Reference\": \"Reference (参考)\",\n    \"reference_adain\": \"reference_adain (仅参考输入图 - 自适应实例规范)\",\n    \"reference_adain+attn\": \"reference_adain+attn (仅参考输入图 - 自适应实例规范 + Attention链接)\",\n    \"reference_only\": \"reference_only (仅参考输入图)\",\n    \"Ref image (for conviently locate regions)\": \"参考图（用于方便定位区域）\",\n    \"refresh\": \"刷新\",\n    \"Refresh\": \"刷新\",\n    \"Refresh Civitai Helper\": \"刷新 Civitai 助手\",\n    \"Refresh Civitai Helper's additional buttons\": \"刷新 Civitai 助手的附加按钮\",\n    \"Refresh Civitai Helper's model card buttons\": \"刷新 Civitai 助手 的模型卡片按钮\",\n    \"Refresh data\": \"刷新数据\",\n    \"Refresh extension list\": \"刷新扩展列表\",\n    \"Refresh models\": \"刷新模型列表\",\n    \"Refresh openOutpaint\": \"刷新 openOutpaint\",\n    \"Refresh page\": \"刷新页面\",\n    \"Refresh TAC temp files\": \"刷新 TAC 缓存文件\",\n    \"regex - e.g. ^(?!.*Hires).*$\": \"正则表达式 - 如 ^(?!.*Hires).*$\",\n    \"Region 1\": \"区域 1\",\n    \"Region 2\": \"区域 2\",\n    \"Region 3\": \"区域 3\",\n    \"Region 4\": \"区域 4\",\n    \"Region 5\": \"区域 5\",\n    \"Region 6\": \"区域 6\",\n    \"Region 7\": \"区域 7\",\n    \"Region 8\": \"区域 8\",\n    \"Region Prompt Control\": \"分区提示词控制\",\n    \"Regions\": \"分区\",\n    \"Regular expression; if weights's name matches it, the weights is not written to the resulting checkpoint. Use ^model_ema to discard EMA weights.\": \"输入正则表达式。键名匹配该表达式的权重将从最终合并模型中剔除。使用 ^model_ema 可剔除 EMA 权重。\",\n    \"Related to original file\": \"与原始文件相关\",\n    \"Related to output file\": \"与输出文件相关\",\n    \"Reload Cache List\": \"重载缓存列表\",\n    \"Reload checkpoint\": \"刷新模型列表\",\n    \"Reload Checkpoints\": \"重新加载模型\",\n    \"Reload custom script bodies (No ui updates, No restart)\": \"重新加载自定义脚本主体（不进行界面更新及重启）\",\n    \"Reloading...\": \"正在重新加载...\",\n    \"Reload Presets\": \"重载预设\",\n    \"Reload/Save Settings (config.json)\": \"重新载入/保存设置 (config.json)\",\n    \"Reload scripts\": \"重载脚本\",\n    \"Reload settings\": \"重新载入设置\",\n    \"Reload Tags\": \"重载标签\",\n    \"Reload the last SD checkpoint back into VRAM\": \"重新将上次使用的 Stable Diffusion 模型加载到显存中\",\n    \"Reload UI\": \"重载前端\",\n    \"Reload UI needed to apply\": \"需重启前端\",\n    \"Reloat List\": \"重新加载列表\",\n    \"remake dimension\": \"重制维度\",\n    \"Remember this choice?\": \"记住这个选择？\",\n    \"➖ Remove\": \"➖ 移除\",\n    \"Remove\": \"移除\",\n    \"Remove all point prompts\": \"移除所有标记点\",\n    \"Remove Auto Trans\": \"移除自动翻译\",\n    \"Remove background\": \"移除背景\",\n    \"Remove background image\": \"移除背景图片\",\n    \"Remove duplicated tag\": \"删除重复标签\",\n    \"Remove occluded edges\": \"移除遮挡边缘\",\n    \"Remove selected\": \"移除已选择的图片\",\n    \"renaissance\": \"renaissance (文艺复兴)\",\n    \"Rename keyframes.\": \"重命名关键帧。\",\n    \"Renoise kernel size\": \"重铺噪声大小\",\n    \"Renoise strength\": \"重铺噪声强度\",\n    \"Replace or save the selected component.\": \"替换或保存所选组件\",\n    \"replace preview image with currently selected in gallery\": \"用当前网页输出中选中的图像替换预览图像\",\n    \"Replace underscores with spaces on insertion\": \"插入时用空格替换下划线\",\n    \"Replace '_' with ' '(Does not affect the function to add tokens using add_token.txt.)\": \"用空格替换下划线（不影响使用 add_token.txt 添加 Token 的功能）\",\n    \"replicate\": \"复制\",\n    \"Request browser notifications\": \"请求浏览器通知权限\",\n    \"(requires restart)\": \"(需要重启)\",\n    \"Requires the\": \"需要安装\",\n    \"reroll\": \"回滚\",\n    \"Reroll blank frames\": \"回滚空白帧\",\n    \"reset\": \"重置\",\n    \"↻ Reset\": \"↻ 重置\",\n    \"Reset\": \"重置\",\n    \"\\uD83C\\uDFA5 Reset Camera\": \"\\uD83C\\uDFA5 重置镜头\",\n    \"Reset default (Reload UI needed to apply)\": \"重置为默认值（需重载UI）\",\n    \"Reset mixer\": \"重置合并设置\",\n    \"\\uD83E\\uDDCD Reset Pose\": \"\\uD83E\\uDDCD 重置姿态\",\n    \"Reset Tile Size\": \"重置区块大小\",\n    \"resizable\": \"可缩放\",\n    \"Resize\": \"缩放比例\",\n    \"Resize and fill\": \"缩放后填充空白\",\n    \"Resize and Fill\": \"缩放后填充空白\",\n    \"Resize by\": \"重绘尺寸倍数\",\n    \"Resize height to\": \"将高度调整为\",\n    \"Resize image to target resolution. Unless height and width match, you will get incorrect aspect ratio.\": \"将图像大小调整为目标分辨率。除非高度和宽度匹配，否则你将获得不正确的纵横比\",\n    \"Resize mode\": \"缩放模式\",\n    \"Resize Mode\": \"缩放模式\",\n    \"Resize seed from height\": \"从高度中调整种子\",\n    \"Resize seed from width\": \"从宽度中调整种子\",\n    \"Resizes image to this height. If 0, height is inferred from either of two nearby sliders.\": \"将图像调整到此高度。如果为0，则从附近的两个滑块中的任意一个推断其高度。\",\n    \"Resizes image to this width. If 0, width is inferred from either of two nearby sliders.\": \"将图像调整到此宽度。如果为0，则从附近的两个滑块中的任意一个推断其宽度。\",\n    \"Resize the image so that entirety of image is inside target resolution. Fill empty space with image's colors.\": \"调整图像大小，使整个图像位于目标分辨率内\\n用图像的颜色填充空白区域\",\n    \"Resize the image so that entirety of target resolution is filled with the image. Crop parts that stick out.\": \"调整图像大小，使整个目标分辨率都被图像填充\\n裁剪多余部分\",\n    \"Resize to\": \"重绘尺寸\",\n    \"Resize width to\": \"将宽度调整为\",\n    \"Resizing objective\": \"缩放设置\",\n    \"Resolution\": \"分辨率\",\n    \"Restart\": \"重启\",\n    \"Restart debug\": \"重启调试\",\n    \"Restart server\": \"重启服务器\",\n    \"Restart UI\": \"重载前端\",\n    \"Restore defaults\": \"恢复默认\",\n    \"Restore Face\": \"面部修复\",\n    \"Restore faces\": \"面部修复\",\n    \"Restore Faces\": \"面部修复\",\n    \"Restore faces after ADetailer\": \"在 After Detailer 之后修复面部\",\n    \"Restore faces after ADetailer 2nd\": \"在 After Detailer 之后修复面部\",\n    \"Restore faces after ADetailer 3rd\": \"在 After Detailer 之后修复面部\",\n    \"Restore faces after ADetailer 4th\": \"在 After Detailer 之后修复面部\",\n    \"Restore faces after ADetailer 5th\": \"在 After Detailer 之后修复面部\",\n    \"Restore Faces, Tiling & more\": \"面部修复，平铺图等更多选项\",\n    \"Restore Last Scene\": \"恢复上次场景\",\n    \"Restore low quality faces using GFPGAN neural network\": \"使用 GFPGAN 神经网络修复低质量面部\",\n    \"Restore progress\": \"恢复进程\",\n    \"Restore Selected Config\": \"恢复所选配置\",\n    \"Result = A\": \"结果 = A\",\n    \"Result = A * (1 - M) + B * M\": \"结果 = A * (1 - M) + B * M\",\n    \"Result = A + (B - C) * M\": \"结果 = A + (B - C) * M\",\n    \"Results\": \"结果\",\n    \"Resume Animation\": \"恢复制作动画过程\",\n    \"Resume & Run from file\": \"恢复动画与加载设置\",\n    \"Retouch\": \"修复程度\",\n    \"Reuse original image\": \"复用原图\",\n    \"Reuse seed from last generation, mostly useful if it was randomed\": \"使用上一次生成的随机数种子，用于重现结果\",\n    \"Reverse model sort order\": \"逆序排序\",\n    \"RGB to BGR\": \"RGB 转 BGR\",\n    \"RIFE v4.6 and FILM.\": \"RIFE v4.6 和 FILM.\",\n    \"right\": \"右\",\n    \"right-left\": \"右 - 左\",\n    \"Roll Channels\": \"色彩通道轮替\",\n    \"Rolling factor\": \"梯度放大倍数\",\n    \"romanticism\": \"romanticism (浪漫主义)\",\n    \"Rotate images (clockwise)\": \"旋转图像 (顺时针)\",\n    \"run\": \"运行\",\n    \"Run\": \"运行参数\",\n    \"Run benchmark\": \"运行基准测试\",\n    \"Run from Settings file\": \"加载配置文件\",\n    \"Run Merge\": \"开始合并\",\n    \"Running ebsynth.(on your self)\": \"运行 Ebsynth。（自行操作）\",\n    \"Run on incomplete\": \"中断后仍然运行\",\n    \"Run preprocessor\": \"运行预处理\",\n    \"Run: Sampler, Width, Height, tiling, resize seed.\": \"运行参数： 采样器，宽度，高度，平铺图，种子大小调整\",\n    \"Run: seed, subseed, subseed strength.\": \"运行参数：第二种子，第二种子强度\",\n    \"safetensors\": \"safetensors\",\n    \"SAG Mask Threshold\": \"SAG 蒙版阈值\",\n    \"same to Strength\": \"与强度相同\",\n    \"SAM Model\": \"SAM 模型\",\n    \"sampler\": \"采样器\",\n    \"Sampler\": \"采样方法\",\n    \"Sampler parameters\": \"采样器参数\",\n    \"Sampler schedule\": \"采样器参数表\",\n    \"Sampler Settings\": \"采样器设置\",\n    \"Sampling method\": \"采样方法 (Sampler)\",\n    \"Sampling settings\": \"采样器设置\",\n    \"Sampling steps\": \"迭代步数 (Steps)\",\n    \"Sampling Steps\": \"迭代步数 (Steps)\",\n    \"SAM requires an input image. Please upload an image first.\": \"SAM 需要你先上传一张图片。\",\n    \"saturation\": \"饱和度\",\n    \"save\": \"保存\",\n    \"\\uD83D\\uDCBE Save\": \"\\uD83D\\uDCBE 保存\",\n    \"Save\": \"保存\",\n    \"Save a copy of embedding to log directory every N steps, 0 to disable\": \"每 N 步将 Embedding 的副本保存到日志目录，0 表示禁用\",\n    \"Save a copy of image before applying color correction to img2img results\": \"在对图生图结果应用颜色校正之前保存图像副本\",\n    \"Save a copy of image before applying highres fix.\": \"在进行高分辨率修复前保存初始图像副本\",\n    \"Save a copy of image before doing face restoration.\": \"在进行面部修复前保存图像副本\",\n    \"Save all changes\": \"保存所有更改\",\n    \"Save an csv containing the loss to log directory every N steps, 0 to disable\": \"每 N 步保存一个包含 loss 的 csv 表格到日志目录，0 表示禁用\",\n    \"Save an image to log directory every N steps, 0 to disable\": \"每 N 步保存一张图像到日志目录，0 表示禁用\",\n    \"Save as float16\": \"储存半精度 (float16) 模型\",\n    \"Save as half\": \"保存半精度模型\",\n    \"Save as safetensors\": \"存为 SafeTensors 格式\",\n    \"Save background instead of foreground\": \"保存背景而不是前景\",\n    \"Save changes\": \"保存更改\",\n    \"Save copy of large images as JPG\": \"将超过大小限制的图像保存JPG副本\",\n    \"Save Current Config\": \"保存当前配置\",\n    \"Save current settings\": \"保存当前设置\",\n    \"Save current settings as default\": \"将当前设置保存为默认值\",\n    \"Save depth map\": \"保存深度图\",\n    \"Save DepthMap\": \"保存深度图\",\n    \"Save depth maps\": \"保存深度图\",\n    \"Save generated images within tensorboard.\": \"在 tensorboard 中保存所生成的图像\",\n    \"Save grids to a subdirectory\": \"将网格图保存到子目录\",\n    \"Save images before ADetailer\": \"在进行后期细节修复前保存原始生成图片\",\n    \"Save images to a subdirectory\": \"将图像保存到子目录\",\n    \"Save images with embedding in PNG chunks\": \"保存嵌入 Embedding 模型的 PNG 图片\",\n    \"Save init images when using img2img\": \"使用图生图时保存初始图像\",\n    \"Save JSON\": \"保存为 JSON 格式\",\n    \"Save mask\": \"保存蒙版\",\n    \"Save masked image\": \"保存蒙版后图像\",\n    \"Save mask previews\": \"保存蒙版预览\",\n    \"Save Metadata\": \"保存元数据\",\n    \"Save metadata (.safetensors only)\": \"保存元数据 (仅限 .safetensors)\",\n    \"save model\": \"保存模型\",\n    \"Save original image\": \"保存原始图像\",\n    \"Save original image with mask and bounding box\": \"保存带有蒙版和箱体的原始图像\",\n    \"Save PNG\": \"保存为 PNG 格式\",\n    \"\\uD83D\\uDCBE\\uD83E\\uDDCD Save Pose\": \"\\uD83D\\uDCBE\\uD83E\\uDDCD 保存姿态\",\n    \"Save preprocessed\": \"保存预处理\",\n    \"Save Preset\": \"保存预设\",\n    \"Save Presets\": \"保存预设\",\n    \"Save preview\": \"保存预览\",\n    \"Save Preview(s) Frequency\": \"保存预览图的频率\",\n    \"Save ranking in image's pnginfo\": \"在PNG图片信息中保存评分\",\n    \"Save & Restart\": \"保存并重启\",\n    \"Save Scene\": \"保存场景\",\n    \"save setting\": \"保存设置\",\n    \"Save Setting\": \"保存设置\",\n    \"save settings\": \"储存设置\",\n    \"Save Settings\": \"保存设置\",\n    \"Saves Optimizer state as separate *.optim file. Training of embedding or HN can be resumed with the matching optim file.\": \"将优化器状态保存为单独的 optim 文件。在训练嵌入式模型或者超网格化模型时可以根据匹配上的 optim 文件恢复训练进度\",\n    \"Save style\": \"将当前提示词储存为预设样式\",\n    \"save successful\": \"保存成功\",\n    \"Save text information about generation parameters as chunks to png files\": \"将图片生成参数保存到 PNG 文件中\",\n    \"Save textual inversion and hypernet settings to a text file whenever training starts.\": \"每次训练开始时保存 TI 和 Hypernetwork 设置到文本文件中\",\n    \"Save to Presets\": \"保存到预设\",\n    \"Save vector to text file\": \"将向量保存到文本文件\",\n    \"Save with JSON\": \"保存为 JSON 格式\",\n    \"Saving images/grids\": \"图片保存设置\",\n    \"Saving to a directory\": \"保存到文件夹\",\n    \"Scale\": \"尺度\",\n    \"Scale by\": \"缩放倍数\",\n    \"Scale Factor\": \"放大倍数\",\n    \"Scale to\": \"缩放到\",\n    \"Scan\": \"扫描\",\n    \"Scan Exif-/.txt-data (initially slower, but required for many features to work)\": \"扫描图片的 Exif 信息与同名 txt 数据文件（初始读取速度较慢，许多功能都需要需要本选项启用）\",\n    \"Scan Models for Civitai\": \"扫描并匹配 Civitai 模型记录\",\n    \"Scanning takes time, just wait. Check console log for detail\": \"扫描需要一段时间，请耐心等待。检查控制台日志以查看详情。\",\n    \"scene\": \"scene (情景)\",\n    \"schedule\": \"参数表\",\n    \"scheduler type\": \"调度器类型\",\n    \"sci-fi\": \"sci-fi (科幻电影)\",\n    \"Scoring type\": \"评分类型\",\n    \"screen\": \"屏幕\",\n    \"Scribble\": \"Scribble (涂鸦)\",\n    \"scribble_hed\": \"scribble_hed (涂鸦 - 合成)\",\n    \"scribble_pidinet\": \"scribble_pidinet (涂鸦 - 手绘)\",\n    \"scribble_xdog\": \"scribble_xdog (涂鸦 - 强化边缘)\",\n    \"script\": \"脚本\",\n    \"Script\": \"脚本\",\n    \"Script Enabled\": \"启用脚本\",\n    \"Script names to apply to ADetailer (separated by comma)\": \"应用于 After Detailer 的脚本名称 (用逗号分隔)\",\n    \"scroll\": \"滚动\",\n    \"sculpture\": \"sculpture (雕塑)\",\n    \"sd-parseq manifest\": \"sd-parseq 配置文件\",\n    \"SD VAE\": \"外挂 VAE 模型\",\n    \"Seams  denoise strenght\": \"接缝重绘幅度\",\n    \"Seams fix\": \"接缝修复\",\n    \"Seams Mask blur (offset pass only)\": \"接缝蒙版边缘模糊程度 (仅偏移层)\",\n    \"Seams padding\": \"接缝填充度\",\n    \"Seams Width\": \"接缝宽度\",\n    \"search\": \"搜索\",\n    \"Search\": \"搜索\",\n    \"Search...\": \"检索...\",\n    \"Search and Replace\": \"搜索与替换\",\n    \"Search anything : Prompt, Size, Model, ...\": \"检索任意内容: 提示词, 尺寸, 模型, ...\",\n    \"Search by alias\": \"按别名检索\",\n    \"Search by translation\": \"按照译文检索\",\n    \"Search for embeddings\": \"检索嵌入式模型 (Embeddings)\",\n    \"Search for hypernetworks\": \"检索超网络\",\n    \"Search for Loras\": \"检索 Lora 模型\",\n    \"Search for LyCORIS/LoHa\": \"检索 LyCORIS/LoHa 模型\",\n    \"Search for wildcards\": \"检索通配符\",\n    \"Search Mode\": \"搜索模式\",\n    \"Search negative prompt\": \"检索反向提示词\",\n    \"Search Text\": \"搜索文本\",\n    \"seascape\": \"seascape (海景)\",\n    \"Secondary model (B)\": \"模型 B\",\n    \"See\": \"查看\",\n    \"seed\": \"随机数种子 (seed)\",\n    \"Seed\": \"随机数种子 (Seed)\",\n    \"Seed behavior\": \"种子生成方式\",\n    \"Seed iter N\": \"种子迭代量 N\",\n    \"Seed of a different picture to be mixed into the generation.\": \"将要参与生成的另一张图的随机种子\",\n    \"Seed schedule\": \"种子数表\",\n    \"seed_schedule should start and end on the same seed.\": \"种子数表应该在同一种子上开始和结束。\",\n    \"See here for explanation of each parameter.\": \"有关每个参数的说明，请点击 这里 查看。\",\n    \"See the progress.\": \"查看图像增强的实时预览进程\",\n    \"Seg\": \"Seg (语义分割)\",\n    \"Segment Anything\": \"Segment Anything (分离图像元素)\",\n    \"Segment Anything Output\": \"分离元素结果\",\n    \"Segment Anything status\": \"Segment Anything 状态\",\n    \"segmentation prompt\": \"图像切分提示词\",\n    \"Segmentation status\": \"语义分割状态\",\n    \"seg_ofade20k\": \"seg_ofade20k (语义分割 - OneFormer 算法 - ADE20k 协议)\",\n    \"seg_ofcoco\": \"seg_ofcoco (语义分割 - OneFormer 算法 - COCO 协议)\",\n    \"seg_ufade20k\": \"seg_ufade20k (语义分割 - UniFormer 算法 - ADE20k 协议)\",\n    \"Select a component class or specific component.\": \"选择一个组件类或特定组件\",\n    \"Select activation function of hypernetwork. Recommended : Swish / Linear(none)\": \"超网络的激活函数。推荐 Swish / Linear (线性)\",\n    \"Select components to hide\": \"选择要隐藏的组件\",\n    \"(select Disco output format).\": \" (选择 Disco 输出格式) .\",\n    \"Selected\": \"选择\",\n    \"(selected items appear first)\": \"(选中组件优先显示)\",\n    \"Select joining char\": \"选择分隔符\",\n    \"Select keyframes to be given to ebsynth.\": \"选择关键帧提交到 Ebsynth。\",\n    \"Select Layer weights initialization. Recommended: Kaiming for relu-like, Xavier for sigmoid-like, Normal otherwise\": \"选择初始化层权重的方案。建议：类relu 用 Kaiming； 类sigmoid 用 Xavier；其它就用正态\",\n    \"Select prompt\": \"选择提示词\",\n    \"Select Translater\": \"选择翻译引擎\",\n    \"Select which Real-ESRGAN models to show in the web UI.\": \"选择在 web UI 显示的 Real-ESRGAN 模型\",\n    \"Select which Real-ESRGAN models to show in the web UI. (Requires restart)\": \"选择在网页界面显示哪些 Real-ESRGAN 模型。(需重启)\",\n    \"Send dimensions to stable diffusion\": \"将当前图片尺寸信息发送到生成设置\",\n    \"Send image to tag selection\": \"发送到 标签 (Tag) 选择\",\n    \"Send pose to /openpose_editor_index for edit.\": \"发送姿态图到 openpose editor 页面编辑\",\n    \"Send prompt up\": \"发送提示词到上方\",\n    \"Send seed when sending prompt or image to other interface\": \"将提示词或者图像发送到其他界面时，同时传送种子数值\",\n    \"Send size when sending prompt or image to another interface\": \"将提示词或者图像发送到其他界面时，同时传送图像尺寸\",\n    \"Send this image to ControlNet.\": \"将图片发送至 ControlNet\",\n    \"Send to\": \"发送到\",\n    \"Send to Blend\": \"发送到 混合\",\n    \"Send to Canvas Editor\": \"发送到 Canvas Editor\",\n    \"Send to ControlNet\": \"发送到 ControlNet\",\n    \"Send to Effect\": \"发送到 效果\",\n    \"Send to extras\": \"发送到 后期处理\",\n    \"Send to img2img\": \"发送到 图生图\",\n    \"Send to img2img:\": \"发送到 图生图：\",\n    \"Send to img2img ControlNet\": \"发送到 图生图 ControlNet\",\n    \"Send to inpaint\": \"发送到 重绘\",\n    \"Send to inpaint upload\": \"发送到 重绘蒙版\",\n    \"Send to ip2p\": \"发送到 图生图 pix2pix\",\n    \"Send to Layer1\": \"发送到图层 1\",\n    \"Send to Layer2\": \"发送到图层 2\",\n    \"Send to Layer3\": \"发送到图层 3\",\n    \"Send to Layer4\": \"发送到图层 4\",\n    \"Send to Layer5\": \"发送到图层 5\",\n    \"Send to Multi-Merge\": \"发送到 多重合并\",\n    \"Send to openOutpaint\": \"发送到 openOutpaint\",\n    \"Send to txt2img\": \"发送到 文生图\",\n    \"Send to txt2img:\": \"发送到 文生图：\",\n    \"Send to txt2img and img2img\": \"发送到 文生图和图生图\",\n    \"Send to txt2img ControlNet\": \"发送到 文生图 ControlNet\",\n    \"(separate by comma)\": \"(用逗号分隔)\",\n    \"Separate UNet/Text Encoder weights\": \"单独设置 UNet/Text Encoder 权重\",\n    \"Separate values for X axis using commas.\": \"使用逗号分隔 X 轴的值\",\n    \"Separate values for Y axis using commas.\": \"使用逗号分隔 Y 轴的值\",\n    \"Sequential Merge Parameters\": \"合并参数序列\",\n    \"Sequential XY Merge and Generation\": \"顺序合并并生成 XY 图\",\n    \"Server start time\": \"服务器启动时间\",\n    \"\\uD83D\\uDDBC Set\": \"\\uD83D\\uDDBC 设置\",\n    \"Set \\\"Hires steps\\\" to [0], if you need\": \"设置 \\\"高分迭代步数\\\" 为 [0], 如果你需要\",\n    \"Set Init tab's strength slider greater than 0. Recommended value (.65 - .80).\": \"将Init选项卡的强度滑块设置为大于0。建议值（.65-.80）。\",\n    \"Set Random Pose\": \"设置随机姿势\",\n    \"Set 'seed_behavior' to 'schedule' under the Seed Scheduling section below.\": \"在下面的“种子调度”部分下，将 “seed_behavior” 设置为 “schedule” 。\",\n    \"Set the Latent Couple extension to 2 area’s (standard setting)\": \"设置 Latent Couple 插件为 2 分区域 (标准设置)\",\n    \"Set the preprocessor to [invert] If your image has white background and black lines.\": \"如果使用白底黑线图片，请使用 \\\"invert\\\" 预处理器。\",\n    \"Set the prompt compounder to: 2\": \"设置提示词混合为: 2\",\n    \"Set the Prompt Seperator mode to: automatic\": \"设置提示词分隔模式为: 自动\",\n    \"Set the Prompt Seperator mode to: prefix AND prompt + suffix\": \"设置提示词分隔模式为: prefix AND prompt + suffix （前缀 AND 提示词 + 后缀）\",\n    \"Set the Prompt seperator to: AND\": \"设置提示词分隔符为: AND\",\n    \"Set the strength to 0 automatically when no init image is used\": \"当无初始化图像在再被使用时，强度值将自动设置为 0\",\n    \" Setting\": \"设置\",\n    \"(setting entries that appear at the top of page rather than in settings tab)\": \"(添加位于网页界面顶部的选项, 而不是在设置标签栏中)\",\n    \"settings\": \"设置\",\n    \"Settings\": \"设置\",\n    \"Settings->ControlNet->Allow other script to control this extension\": \"设置->ControlNet->允许其他脚本控制此插件\",\n    \"Settings File\": \"设置文件\",\n    \"Settings file Path can be relative to webui folder OR full - absolute\": \"设置文件路径可以相对于 SD-WebUI 根目录，也可以是完整的绝对路径\",\n    \"settings for\": \"设置。包括: \",\n    \"Settings->Interrogate Option->Interrogate: include ranks of model tags matches in results\": \"设置->反推设置->反推结果包含模型标签匹配等级\",\n    \"Settings stack. If it's not checked, it wont overwrite. Apply one, then another. Reset is old, update how you need.\": \"设置堆栈。如果未选中，则不会覆盖。应用一个，再应用另一个。重置已过时，请根据需要进行更新。\",\n    \"Set your total number of keyframes to be 21 more than the last inserted keyframe image.\": \"将关键帧总数设置为比上次插入的关键帧图像多21个。\",\n    \"SFW mode \\uD83D\\uDC40 (blur all images)\": \"健全模式 \\uD83D\\uDC40 (模糊所有图像)\",\n    \"Shapes\": \"形状\",\n    \"Sharpness:\": \"锐化度\",\n    \"should be 2 or lower.\": \"应小于等于2\",\n    \"Show all pages\": \"显示所有设置页\",\n    \"Show all results\": \"展示所有候选标签\",\n    \"Show batch images in gradio gallerie output\": \"在 Gradio Gallerie 输出中批量显示图像\",\n    \"Show batch images in gradio gallery output\": \"在 Gradio Gallery 输出中批量显示图像\",\n    \"Show Button On Thumb Mode\": \"在缩略图模式下显示按钮\",\n    \"Show cards for models in hidden directories\": \"显示隐藏目录中的模型卡片\",\n    \"Show Civitai Link events in the console\": \"在控制台输出 Civitai Link 事件\",\n    \"Show command for conversion\": \"显示转换命令行\",\n    \"Show console debug\": \"在控制台显示调试信息\",\n    \"Show DepthMap\": \"展示深度图\",\n    \"Show extra networks\": \"显示扩展模型面板\",\n    \"Show extra options\": \"显示额外选项\",\n    \"Show generation progress in window title.\": \"在窗口标题中显示生成进度\",\n    \"Show grid in results for web\": \"在网页输出结果中显示网格图\",\n    \"Show HeatMap\": \"展示热力图\",\n    \"Show hidden directories\": \"显示隐藏目录\",\n    \"Show/hide extra networks\": \"显示/隐藏扩展模型\",\n    \"Show/Hide Generation Info\": \"显示/隐藏生成信息\",\n    \"Show images zoomed in by default in full page image viewer\": \"在网页全屏图像查看器中，默认放大显示图像\",\n    \"Show intermediate steps\": \"显示中间步骤\",\n    \"Show live previews of the created image\": \"显示当前生成图像的实时预览\",\n    \"Show live tag translation below prompt (WIP, expect some bugs)\": \"在提示词下方显示实时标签翻译 (未完成，预计会有一些bug)\",\n    \"Show more info\": \"显示更多信息\",\n    \"Show '?' next to tags, linking to its Danbooru or e621 wiki page (Warning: This is an external site and very likely contains NSFW examples!)\": \"在 Tag 旁边显示 '?' , 链接到其 Danbooru 或 e621 维基页面（警告：外部网站可能包含 NSFW 内容!）\",\n    \"Show Preview\": \"显示预览\",\n    \"Show previews of all images generated in a batch as a grid\": \"通过网格图预览单个批次的所有图像\",\n    \"Show progressbar\": \"显示进度条\",\n    \"Show progress indicator\": \"显示进度指示器\",\n    \"Show result images\": \"显示输出图像\",\n    \"Show verbose debug info at console\": \"在控制台中输出详尽的调试信息\",\n    \"Show warnings in console.\": \"在控制台中显示警告\",\n    \"Show Width/Height and Batch sliders in same row\": \"将批次与批量设置整合到长宽设置的右侧\",\n    \"shuffle\": \"shuffle (随机洗牌)\",\n    \"Shuffle\": \"Shuffle (随机洗牌)\",\n    \"Shuffleing tags by ',' when create texts.\": \"创建文本时打乱以 ',' 分割的标签\",\n    \"Shuffle tags by ',' when creating prompts.\": \"创建提示词时按 ',' 打乱标签(tags)\",\n    \"Shutdown server\": \"关闭服务器\",\n    \"Sidebar\": \"侧边栏\",\n    \"Sides\": \"每边张数\",\n    \"Sigma adjustment for finding noise for image\": \"为寻找图中噪点的 Sigma 调整\",\n    \"sigma churn\": \"sigma churn (流失率)\",\n    \"sigma max\": \"最大 Sigma\",\n    \"sigma min\": \"最小 Sigma\",\n    \"sigma noise\": \"sigma noise (噪声标准差)\",\n    \"Sigma noise\": \"Sigma 噪声\",\n    \"Sigma Noise\": \"Sigma 噪声\",\n    \"Sigma schedule\": \"Sigma 值表\",\n    \"sigma tmin\": \"sigma tmin (最小时间步长)\",\n    \"Simple\": \"单一值\",\n    \"Simple (Auto-value)\": \"单一值（自动取值）\",\n    \"Single\": \"单次处理\",\n    \"single image\": \"单张图片\",\n    \"Single Image\": \"单张图片\",\n    \"Single process\": \"单次处理\",\n    \"Size of the face when recreating\": \"重建脸部的尺寸\",\n    \"Size of the thumbnails (px)\": \"缩略图大小 (单位: 像素)\",\n    \"Size to generate\": \"生成规格\",\n    \"sketch\": \"涂鸦\",\n    \"Sketch\": \"涂鸦\",\n    \"Skip\": \"跳过\",\n    \"Skip generation and use (edited/custom) depthmaps in output directory when a file exists.\": \"当文件已存在时, 跳过生成并在输出目录中使用 (编辑后/自定义) 的深度图\",\n    \"Skip img2img processing when using img2img initial image\": \"使用图生图初始图像时跳过图生图处理\",\n    \"(skip negative prompt for some steps when the image is almost ready; 0=disable, higher=faster)\": \"(当图像接近生成完成时, 跳过部分步数的负面提示词影响; 0=禁用, 数值越大=越快速)\",\n    \"Skip negative prompt for steps where image is already mostly denoised; the higher this value, the more skips there will be; provides increased performance in exchange for minor quality reduction.\": \"对图像已经完成大部分去噪的采样步数, 跳过反向提示词; 这个值越高, 跳过的步数就越多; 以轻微的质量降低换取更高的性能\",\n    \"Skip NSFW Preview Images\": \"下载预览图时跳过含成人内容的图像\",\n    \"SKip NSFW Preview images\": \"下载预览图时跳过含成人内容的图像\",\n    \"SKip NSFW Preview Images\": \"下载预览图时跳过含成人内容的图像\",\n    \"Skip/Reset CLIP position_ids\": \"跳过或重置 CLIP position_ids 键值\",\n    \"Skip video creation\": \"跳过视频生成\",\n    \"Smart subject\": \"智能主题\",\n    \"Smart subject tries to determine what to and not to generate based on your subject. Example, if your Overwrite subject is formed like this: Obese man wearing a kimono\": \"智能主题会尝试根据你的主题决定要生成什么和避免生成什么。\\n比如说，如果你的覆盖主题是这样的格式：穿着和服的肥胖男子\",\n    \"Socket port for image browser\": \"Cozy 图库浏览器的 Socket 端口\",\n    \"SoftEdge\": \"SoftEdge (软边缘)\",\n    \"softedge_hed\": \"softedge_hed (HED 软边缘检测)\",\n    \"softedge_hedsafe\": \"SoftEdge_HEDSafe (软边缘检测 - 保守 HED 算法)\",\n    \"softedge_pidinet\": \"SoftEdge_PiDiNet (软边缘检测 - PiDiNet 算法)\",\n    \"softedge_pidisafe\": \"SoftEdge_PiDiNetSafe (软边缘检测 - 保守 PiDiNet 算法)\",\n    \"soft_light\": \"柔光\",\n    \"solution.\": \"的解决方法。\",\n    \"Sort bounding boxes by\": \"按以下方式对边界框进行排序\",\n    \"sort by\": \"排序方式\",\n    \"Sort by\": \"排序方式\",\n    \"Sort by alphabetical order\": \"按首字母顺序排序\",\n    \"Sort LoRA models by\": \"低秩微调 (LoRA) 模型排序方式\",\n    \"Sort Order\": \"排序方式\",\n    \"Sort tags\": \"排序标签\",\n    \"(so they are used as literal brackets and not for emphasis)\": \"(启用后作为字面意义上的括号使用, 不起强调作用)\",\n    \"Soundtrack path\": \"音轨路径\",\n    \"Source\": \"来源\",\n    \"Source Checkpoint\": \"源模型\",\n    \"Source directory\": \"源目录\",\n    \"Source URL where this model could be found\": \"该模型发布的原始网址\",\n    \"space\": \"space (空格/空间艺术)\",\n    \"Specific branch name\": \"特定分支名\",\n    \"specify a custom settings file and ignore settings displayed in the interface\": \"指定自定义设置文件并忽略界面中显示的设置\",\n    \"Specify the amount that you wish to expand the mask by (recommend 0-10)\": \"设定蒙版扩展量（建议0-10）\",\n    \"Specify the amount that you wish to expand the mask by (recommend 30)\": \"设定蒙版扩展量（建议30）\",\n    \"specify your own seed schedule (found on the Keyframes page)\": \"指定你自己的种子数表（可在关键帧选项卡中找到）\",\n    \"split\": \"分离\",\n    \"Split based on cuts (as well)\": \"基于分割进行提取（同时）\",\n    \"Split image overlap ratio\": \"分割图像重叠比率\",\n    \"Split image threshold\": \"图像分割阈值\",\n    \"Split over-sized images\": \"分割过大的图像\",\n    \"Split oversized images\": \"分割过大的图像\",\n    \"Split oversized images into two\": \"将过大的图像分为两份\",\n    \"Split Video\": \"分割视频\",\n    \"square\": \"square (方图)\",\n    \"SSAA\": \"超级采样抗锯齿\",\n    \"stability_score_offset\": \"稳定性得分偏移\",\n    \"stability_score_thresh\": \"稳定性得分阈值\",\n    \"stability_score_threshold\": \"稳定性得分阈值\",\n    \"Stable Diffusion\": \"Stable Diffusion\",\n    \"Stable Diffusion checkpoint\": \"Stable Diffusion 模型\",\n    \"Stable Diffusion checkpoint autoload on server start\": \"在服务器启动时自动加载 Stable Diffusion 模型\",\n    \"Stackable\": \"可堆叠\",\n    \"Stackable checkbox is not used for saves, it's used when making a selection from the dropdown, whether to apply as stackable or not\": \"可堆叠复选框不用于保存，它用于从下拉列表中进行选择，无论是否应用为可堆叠\",\n    \"stage 1\": \"步骤 1\",\n    \"stage 2\": \"步骤 2\",\n    \"stage 3\": \"步骤 3\",\n    \"(Stage 3, 4, and 6 only show a guide and do nothing actual processing.)\": \"（步骤 3、4和6只显示指南，不做实际的操作。）\",\n    \"stage 3.5\": \"步骤 3.5\",\n    \"stage 4\": \"步骤 4\",\n    \"stage 5\": \"步骤 5\",\n    \"stage 6\": \"步骤 6\",\n    \"stage 7\": \"步骤 7\",\n    \"stage 8\": \"步骤 8\",\n    \"stained glass\": \"stained glass (彩色玻璃)\",\n    \"Start Auto Translate\": \"开始自动翻译\",\n    \"Start batch process\": \"开始批量处理\",\n    \"Start drawing\": \"开始绘制\",\n    \"start extracting the input video only from this frame number\": \"你所需要提取开始初始化视频的帧数\",\n    \"Start generating and upscaling!\": \"开始生成并放大\",\n    \"Starting Control Step\": \"引导介入时机\",\n    \"Start steps\": \"开始步数\",\n    \"Start training.\": \"开始训练\",\n    \"Start WebUi with option --api for this to work.\": \"启动 WebUi 时加入 --api 启动参数来保证本标签页的功能正常工作。\",\n    \"State\": \"运行状态\",\n    \"status\": \"状态\",\n    \"Status:\": \"状态: \",\n    \"Std\": \"标准差\",\n    \"step\": \"迭代步数\",\n    \"Step\": \"迭代步数\",\n    \"Steps\": \"迭代步数\",\n    \"Steps schedule\": \"迭代步数计划表\",\n    \"Sticker\": \"贴纸\",\n    \"still life\": \"still life (静物画)\",\n    \"*Stitch frames to video*\": \"*将帧缝合为视频*\",\n    \"Stop\": \"停止\",\n    \"Stop processing current image and continue processing.\": \"停止处理当前图像，并继续处理下一个\",\n    \"Stop processing images and return any results accumulated so far.\": \"停止处理图像，并返回迄今为止累积的所有结果\",\n    \"stop the extraction of the video at this frame number. -1 for no limits\": \"你所需要提取结束初始化视频的帧数，-1 表示无限制（全部）\",\n    \"Stop XY\": \"停止生成 X/Y 图\",\n    \"Store frames in ram\": \"将帧保存到内存\",\n    \"Store preferences and SVG content locally\": \"在本地保存设置和SVG图像\",\n    \"storybook realism\": \"storybook realism (故事书写实主义/迪士尼艺术)\",\n    \"straight-line\": \"直线\",\n    \"street art\": \"street art (街头艺术)\",\n    \"streetscape\": \"streetscape (街景)\",\n    \"strength\": \"强度\",\n    \"Strength\": \"强度\",\n    \"Strength 0 no init\": \"强度为 0 时停用初始化\",\n    \"Style 1\": \"模版风格 1\",\n    \"Style 2\": \"模版风格 2\",\n    \"Styles\": \"预设样式\",\n    \"Sub directory depth\": \"子目录深度\",\n    \"Sub-folder\": \"子文件夹\",\n    \"Subject Types\": \"主题类型\",\n    \"Submit\": \"提交\",\n    \"Submit results\": \"提交结果\",\n    \"SubSeed\": \"第二种子\",\n    \"Subseed schedule\": \"第二种子参数表\",\n    \"Subseed strength schedule\": \"第二种子强度参数表\",\n    \"Sum\": \"和\",\n    \"sum Twice:(A*(1-alpha)+B*alpha)*(1-beta)+C*beta\": \"两次求和: (A*(1-α)+B*α)*(1-β)+C*β\",\n    \"SuperMerger\": \"超级模型融合\",\n    \"Supported engines:\": \"支持的引擎：\",\n    \"Supports boolean operations: (! - negation, & - and, | - or, ^ - xor, \\\\ - difference, () - nested operations)\": \"支持布尔操作符：（！-否定/取反，&-与，|-或，^-异或，\\\\-差分，()-嵌套操作）\",\n    \"surrealism\": \"surrealism (超现实主义)\",\n    \"Swap axes\": \"互换坐标轴\",\n    \"Swap hotkey combinations for Zoom and Adjust brush resize\": \"交换缩放和调整画笔大小的热键组合\",\n    \"Swap X/Y axes\": \"X/Y 轴互换\",\n    \"Swap X/Z axes\": \"X/Z 轴互换\",\n    \"Swap Y/Z axes\": \"Y/Z 轴互换\",\n    \"Swipe left/right navigates to the next image\": \"左右滑动时导航到下一张图片\",\n    \"Switch prompt between Native language and English\": \"切换提示词显示语言 (母语/英语)\",\n    \"Switch to Inpaint Upload\": \"发送到 重绘蒙版\",\n    \"symbolism\": \"symbolism (象征主义)\",\n    \"Sysinfo\": \"系统信息\",\n    \"System\": \"系统设置\",\n    \"System data\": \"系统信息\",\n    \"System Info\": \"系统信息\",\n    \"T2IA\": \"T2IA (自适应)\",\n    \"t2ia_color_grid\": \"T2ia_Color_Grid (自适应 色彩像素化处理)\",\n    \"t2ia_sketch_pidi\": \"T2ia_Sketch_PiDi (自适应 手绘边缘处理)\",\n    \"t2ia_style_clipvision\": \"T2ia_Style_Clipvision (自适应 风格迁移处理)\",\n    \"tab\": \"选项卡\",\n    \"Tag Autocomplete\": \"标签自动补全\",\n    \"Tag confidents\": \"标签置信度\",\n    \"Tag filename\": \"选择使用的标签文件名\",\n    \"Tagger\": \"WD 1.4 标签器 (Tagger)\",\n    \"Tagging\": \"打标\",\n    \"Tagging Confidence Threshold\": \"标签置信度阈值\",\n    \"Tag images\": \"多图打标\",\n    \"Tag one image\": \"单图打标\",\n    \"Tags\": \"标签\",\n    \"Target Folder\": \"目标文件夹\",\n    \"Target language\": \"目标语言\",\n    \"Target Language\": \"目标语言\",\n    \"Target tokens (comma separated)\": \"分隔目标提示词(逗号分隔)\",\n    \"Task History\": \"任务历史\",\n    \"Task Queue\": \"任务队列\",\n    \"Tattoo\": \"纹身\",\n    \"temparature\": \"色温\",\n    \"Temporal-Warp\": \"Temporal 修复\",\n    \"TEnc Weight 1\": \"Text Encoder 权重 1\",\n    \"TEnc Weight 2\": \"Text Encoder 权重 2\",\n    \"TEnc Weight 3\": \"Text Encoder 权重 3\",\n    \"TEnc Weight 4\": \"Text Encoder 权重 4\",\n    \"TEnc Weight 5\": \"Text Encoder 权重 5\",\n    \"Tertiary model (C)\": \"模型 C\",\n    \"TEST-MAX-ALL\": \"全部测试\",\n    \"Textbox\": \"文本框\",\n    \"text encoder\": \"文本编码器\",\n    \"Text files directory (optional, will load from input dir if not specified)\": \"文本文件目录 (可选, 如不指定将从输入目录加载)\",\n    \"Text files directory (Optional, will load from input dir if not specified)\": \"文本文件目录 (可选, 如不指定将从输入目录加载)\",\n    \"textile\": \"textile (纺织艺术)\",\n    \"Text input\": \"文本输入\",\n    \"Textual Inversion\": \"嵌入式(T.I. Embedding)\",\n    \"The 1st and last keyframe images should match.\": \"第一个和最后一个关键帧图像应该匹配。\",\n    \"The algorithm is not able to enhance all images.\": \"本算法不能增强所有图像\",\n    \"The annotator directory inside the SAM extension directory is only a symbolic link. This is to save your space and make the extension repository clean.\": \"SAM 扩展目录中的解释器目录只是符号链接。这样能够节省你的硬盘空间，并使扩展库更加有序。\",\n    \"The code for this extension:\": \"本插件的源码仓库: \",\n    \"The current workflow is [text prompt]->[object detection]->[segmentation]. Semantic segmentation support is in Auto SAM panel.\": \"目前的工作流是 [文本提示词]->[对象检测]->[语义分割]。语义分割支持在自动 SAM 面板中。\",\n    \"The denoising curve controls the rate of denoising strength change each loop. Aggressive: Most of the change will happen towards the start of the loops. Linear: Change will be constant through all loops. Lazy: Most of the change will happen towards the end of the loops.\": \"重绘幅度曲线控制每次处理的重绘幅度变化率\\n激进: 处理的 开始阶段 大规模变动重绘幅度\\n线性: 处理的 全部阶段 重绘幅度变化率一致\\n保守: 处理的 结束阶段 大规模变动重绘幅度\",\n    \"The denoising strength for the final loop of each image in the batch.\": \"每一批次中每个图像的最终循环时的重绘幅度\",\n    \"The difference between the last two models will be added to the first. Requires three models; A, B and C. The result is calculated as A + (B - C) * M\": \"后两个模型的差值将叠加在主要模型上。需要输入 A、B、C 三个模型。计算公式为 A + (B - C) * M\",\n    \"the directory in which your mask video is located.\": \"你所需要使用的视频蒙版路径\",\n    \"the directory / URL at which your video file is located for Video Input mode only\": \"视频文件所在的目录/链接，仅适用于视频输入模式\",\n    \"The existing prompt and negative prompt fields are ignored.\": \"会使现有的正向提示词和反向提示词段被忽略。\",\n    \"The frames per second that the video will run at\": \"视频的每秒播放帧数\",\n    \"The height of the output images, in pixels (must be a multiple of 64)\": \"输出图像的高度（像素）（必须能整除于 64）\",\n    \"then use\": \"然后使用\",\n    \"The other site allows for making keyframes using\": \"另一方面，允许关键帧使用 \",\n    \"the path to a custom settings file\": \"自定义设置文件的路径\",\n    \"the path to your init image\": \"初始化图像的路径\",\n    \"the path to your mask image\": \"蒙版文件的路径\",\n    \"the path/ URL to an audio file to accompany the video\": \"视频附带的音频文件的路径 / 链接\",\n    \"The process of creating a video can be divided into the following stages.\": \"创作视频需要以下几个步骤。\",\n    \"There are a lot of special things build in, based on various research papers. Just try it, and let it surprise you.\": \"根据各种研究论文构建了许多特殊效果。尽管试一下，让它给你带来惊喜。\",\n    \"There are an immense number of image types, not only paintings and photo's, but also isometric renders and funko pops.\\nYou can however, overwrite it with the most popular ones.\": \"大量的图像类型，不仅有画作和照片，还有 等距/等轴渲染 和 Funko Pops (玩具人偶) 。\\n不过你可以用最流行的图像类型覆盖它。\",\n    \"There is *no* Batch mode like in vanilla deforum. Please Use the txt2img tab for that.\": \"本插件没有批处理模式，请使用文生图选项卡。\",\n    \"The results are stored in timestamp_prompts.txt.\": \"将结果保存在 timestamp_prompts.txt 中。\",\n    \"the roll effect angle\": \"所旋转的角度（X轴，一般性指水平）\",\n    \"These can be used to add textual inversion and LoRA’s. They can also be used to add your models trigger words.\": \"这里用来添加 嵌入式(T.I. Embedding) 和 LoRA 。同样可以用来添加模型触发词。\",\n    \"the seed value will increment by 1 for each subsequent frame of the animation\": \"对于动画的每个后续帧，种子数将增加 1\",\n    \"the seed will remain fixed across all frames of animation\": \"动画中所有帧的随机种子将被固定\",\n    \"the tilt effect angle\": \"所翻转的垂直角度（Y轴）\",\n    \"The untranslated characters will be translated automatically and will not affect the old translations. Use the function in the lower right corner to easily check and quickly modify the current translation.1,Save the setting;2,Click start button;3,Reload your browser.\": \"未翻译的提示词将自动翻译，不会影响已翻译过的提示词。使用右下方的功能按钮可以快速检查和修改当前的翻译。1.保存设置；2.点击启动按钮；3.重载浏览器。\",\n    \"The WebSocket is currently\": \"WebSocket 当前状态为\",\n    \"the whole folder, generated before, not just the output folder\": \"提前建立好的整个工程目录，而不仅仅是输出文件夹\",\n    \"The width of the output images, in pixels (must be a multiple of 64)\": \"输出图像的宽度（像素，必须能整除于 64）\",\n    \"Third column (reference) image\": \"第三列 (参考) 图像\",\n    \"[this]\": \"[这里]\",\n    \"This generator will generate a complete full prompt for you, based on randomness. You can increase the slider, to include more things to put into the prompt. \\nRecommended is keeping it around 3-7. Use 10 at your own risk.\": \"本生成器会根据随机等级为你生成一段完整的提示词。可以通过滑块提高数值，以在提示词中包含更多的东西。\\n建议保持在3-7左右。使用10的话后果自负。\",\n    \"This is an extra stage.\": \"这是一个额外的步骤。\",\n    \"This is ignored if neither batch run or ebsynth are checked\": \"如果批量处理或 Ebsynth 模式都没有被选中，此项将被忽略\",\n    \"(this is optional. Perform color correction on the img2img results and expect flickering to decrease. Or, you can simply change the color tone from the generated result.)\": \"（此步骤可选。对图生图的结果进行颜色校正，可能会减少视频闪烁。或者，你也可以简单地在生成结果中调色。）\",\n    \"This page allows you to change default values in UI elements on other tabs.\": \"本页面允许你去修改其它标签页中的 UI 默认设置\",\n    \"This panel is for those who want to upload mask to ControlNet inpainting. It is not part of the SAM feature. It might be removed someday when ControlNet support uploading image and mask. It serves as a temporarily workaround to overcome the unavailability of image with mask uploading feature in ControlNet extension.\": \"此面板是为想把蒙版上传到 ControlNet 重绘的人准备的。这不是 SAM 的功能。当某天 ControlNet 支持上传图像和蒙版时，此功能可能会删除。这是一个临时解决方案，以解决 ControlNet 不能上传蒙版的问题。\",\n    \"This preset affects?\": \"该预设中包含？\",\n    \"This regular expression will be used extract words from filename, and they will be joined using the option below into label text used for training. Leave empty to keep filename text as it is.\": \"该正则表达式将用于从文件名中提取单词，并将它们合并到用于训练的标签文本中。留空以保持文件名文本不变。\",\n    \"This requires Controlnet 1.1 extension and the tile resample model, install this if you haven't\\nIn settings for Controlnet, enable \\\"Allow other script to control this extension\\\"\": \"这需要 ControlNet 1.1 插件和 tile resample 预处理器对应的模型，如果没有请安装！\\n在设置页面的 ControlNet 设置中启用 ”允许其它脚本控制本插件“ 。\",\n    \"This requires the Ultimate SD Upscale extension, install this if you haven't\": \"这需要 Ultimate SD Upscale 插件，如果没有请安装！\",\n    \"This string will be used to join split words into a single line if the option above is enabled.\": \"如果启用了上述选项，则此处的字符会用于将拆分的单词接合为同一行\",\n    \"this subreddit\": \"此页面\",\n    \"This was originally a bug in the first release when using multiple batches, now brought back as a feature.\\nRaised by redditor drone2222, to bring this back as a toggle, since it did create interesting results. So here it is.\": \"这原本是第一个版本中使用多批次时的一个 bug ，现在作为一个功能回归。\\n由 redditor: drone2222提出，让它作为一个切换选项功能回归，因为它确实创造了有趣的结果。就是这样一个功能。\",\n    \"This way, you can create unlimited variants of a subject.\": \"通过这种方法，你可以创建同一个主题的无数变种图像。\",\n    \"This way, you don’t ever have to add it manually again. This file won’t be overwritten during upgrades.\": \"通过这个方法，就不需要每次都手动添加。这个文件不会在本插件更新时被覆盖。\",\n    \"Those settings are heavy on DOM modification and might conflict with some others extensions\": \"这些设置对 DOM 修改程度很大, 可能与其它扩展冲突\",\n    \"threshold\": \"threshold (阈值)\",\n    \"Threshold\": \"阈值\",\n    \"Threshold A\": \"阈值 A\",\n    \"Threshold B\": \"阈值 B\",\n    \"Thresholding Mode\": \"阈值模式\",\n    \"Threshold of delta frame edge\": \"增量帧边缘阈值\",\n    \"Threshold schedule\": \"阈值表\",\n    \"Threshold Value Lower\": \"阈值下限\",\n    \"Threshold Value Upper\": \"阈值上限\",\n    \"thumbs\": \"缩略视图\",\n    \"Tile\": \"Tile (分块)\",\n    \"tile_colorfix\": \"tile_colorfix (分块 - 固定颜色)\",\n    \"tile_colorfix+sharp\": \"tile_colorfix+sharp (分块 - 固定颜色 + 锐化)\",\n    \"tile division BG Removers\": \"分块化背景去除\",\n    \"tile_gaussian\": \"Tile_Gaussian (拼贴画模糊处理)\",\n    \"tile height\": \"分块高度\",\n    \"Tile height\": \"分块高度\",\n    \"Tile overlap\": \"分块重叠像素宽度\",\n    \"Tile overlap for ESRGAN upscalers.\": \"ESRGAN 超分辨率的分块块重叠像素大小\",\n    \"Tile overlap for SCUNET upscalers.\": \"SCUNET 超分辨率的分块块重叠像素大小\",\n    \"Tile overlap, in pixels for ESRGAN upscalers. Low values = visible seam.\": \"ESRGAN 超分辨率的分块块重叠像素大小。数值越低意味着分块间的接缝越明显\",\n    \"Tile overlap, in pixels for SCUNET upscalers. Low values = visible seam.\": \"SCUNET 超分辨率的分块重叠像素大小。数值越低意味着分块间的接缝越明显\",\n    \"Tile overlap, in pixels for SwinIR. Low values = visible seam.\": \"SwinIR 的分块重叠像素大小。数值越低意味着分块间的接缝越明显\",\n    \"tile_resample\": \"tile_resample (分块 - 重采样)\",\n    \"Tile size for all SwinIR.\": \"适用所有 SwinIR 系算法的分块尺寸\",\n    \"Tile size for ESRGAN upscalers.\": \"ESRGAN 使用的分块尺寸\",\n    \"Tile size for ESRGAN upscalers. 0 = no tiling.\": \"ESRGAN 使用的分块尺寸 。数值设为0意味着不分块\",\n    \"Tile size for SCUNET upscalers.\": \"SCUNET 超分辨率的分块尺寸\",\n    \"Tile size for SCUNET upscalers. 0 = no tiling.\": \"SCUNET 超分辨率的分块尺寸。数值设为0意味着不分块\",\n    \"tile width\": \"分块宽度\",\n    \"Tile width\": \"分块宽度\",\n    \"Tiling\": \"平铺图 (Tiling)\",\n    \"Time\": \"时间\",\n    \"Time in ms to wait before triggering completion again (Requires restart)\": \"再次显示自动补全标签的等待时间 (单位: 毫秒) (需保存并重启UI)\",\n    \"timestamp\": \"时间戳\",\n    \"Tips\": \"小提示\",\n    \"title\": \"标题\",\n    \"to\": \"到\",\n    \"To apply, go to quick set. Save now works immediately in other tab without restart, filters out non-common between tabs.\": \"要应用，请转到快速设置。现在保存可以立即在其他选项卡中工作，无需重新启动，过滤掉选项卡之间的不常见内容。\",\n    \"to discuss about Cozy Nest\": \"去讨论关于 Cozy Nest 的话题~\",\n    \"To enable, check use_mask in the Init tab\": \"如果需要启用，请检查初始化选项卡中启用蒙版选项是否其启用\",\n    \"to (full path)\": \"到 (输入完整路径)\",\n    \"Toggle overlap ( Technical button, neededs for testing )\": \"重叠切换 (技术性快捷键, 用于测试)\",\n    \"Token\": \"词元\",\n    \"Tokenize\": \"拆分词元\",\n    \"Token Length\": \"词元长度\",\n    \"Token Merging\": \"高分修复TOME\",\n    \"Token Merging - Max downsample\": \"TOME - 最大降采样\",\n    \"Token merging ratio\": \"Token 合并比率\",\n    \"Token Merging - Ratio\": \"TOME 合并比率\",\n    \"Token merging ratio for high-res pass\": \"高分层的 Token 合并比率\",\n    \"Token merging ratio for img2img\": \"图生图的 Token 合并比率\",\n    \"To Language\": \"目标语言\",\n    \"ToMe for Hires. fix\": \"为 Hires. fix 启用 ToMe 优化\",\n    \"ToMe Merging Ratio\": \"ToMe 合并比率\",\n    \"Toolkit\": \"模型工具箱\",\n    \"top\": \"顶部\",\n    \"top-bottom\": \"上 - 下\",\n    \"top_centered\": \"顶部居中\",\n    \"to share your creations and suggestions.\": \"来分享你的创意和提出意见.\",\n    \"(Total)\": \"(合计)\",\n    \"Train\": \"训练\",\n    \"Train an embedding or Hypernetwork; you must specify a directory with a set of 1:1 ratio images\": \"训练嵌入式或超网络模型；必须指定一个具有一组 1:1 宽高比图像的数据集目录\",\n    \"Train EMA\": \"训练 EMA\",\n    \"Train Embedding\": \"训练嵌入式模型\",\n    \"Train Hypernetwork\": \"训练超网络\",\n    \"training\": \"训练相关\",\n    \"Training\": \"训练\",\n    \"Training info\": \"训练信息\",\n    \"Training parameters\": \"训练参数\",\n    \"Train Model\": \"训练模型\",\n    \"Train Text Encoder\": \"训练文本编码器\",\n    \"Trajectory\": \"运动轨迹\",\n    \"Transform Center X\": \"旋转中心点 X 轴\",\n    \"Transform Center Y\": \"旋转中心点 Y 轴\",\n    \"translate\": \"翻译\",\n    \"Translate\": \"翻译\",\n    \"Translated Negative Prompt\": \"反向提示词翻译\",\n    \"Translated Prompt\": \"提示词翻译\",\n    \"Translate Negative Prompt\": \"翻译反向提示词\",\n    \"Translate Prompt\": \"翻译提示词\",\n    \"Translate: x, y, z\": \"移动幅度：x, y, z\",\n    \"Translation display order\": \"翻译显示顺序\",\n    \"Translation filename\": \"翻译文件名\",\n    \"Translation file uses old 3-column translation format instead of the new 2-column one\": \"翻译文件使用旧的三栏式翻译格式，而不是新的二栏式格式\",\n    \"Translation First\": \"译文在上\",\n    \"Translation Service Setting\": \"翻译服务设置\",\n    \"Translation X\": \"平移 X\",\n    \"Translation Y\": \"平移 Y\",\n    \"Translation Z\": \"平移 Z\",\n    \"Transparent\": \"透明\",\n    \"[transparent-background]\": \"[透明背景]\",\n    \"transparent-background\": \"透明背景\",\n    \"transparent-background AND clipseg\": \"透明背景和CLIP分割\",\n    \"transparent-background options\": \"透明背景选项\",\n    \"Transparent PNG\": \"透明PNG\",\n    \"Triple sum:A*(1-alpha-beta)+B*alpha+C*beta\": \"三重加权和: A*(1-α-β)+B*α+C*β\",\n    \"Truncate tags by token count\": \"按词元长度截断标签\",\n    \"Truncate tags by token count.\": \"按词元长度截断标签\",\n    \"Turn on pin_memory for DataLoader. Makes training slightly faster but can increase memory usage.\": \"为数据加载器 (DataLoader) 启用 pin_memory 参数，以提升内存占用的代价提高训练速度\",\n    \"Tweening frames schedule\": \"中间计算帧参数表\",\n    \"txt2img\": \"文生图\",\n    \"TXT2IMG\": \"文生图\",\n    \"txt2img-grids\": \"文生图 (网格)\",\n    \"txt2img history\": \"文生图历史记录\",\n    \"txt2img/img2img UI item order\": \"文生图/图生图界面参数组件顺序\",\n    \"Type\": \"类型\",\n    \"type of image\": \"图像类型\",\n    \"UI related\": \"UI 界面相关\",\n    \"UI tab order\": \"UI 标签栏顺序\",\n    \"ui text\": \"UI 文本\",\n    \"ukiyo-e\": \"ukiyo-e (浮世绘)\",\n    \"ultrawide\": \"ultrawide (超宽图)\",\n    \"Uncheck all copies\": \"取消勾选所有选择\",\n    \"U-Net features\": \"U-Net 特征值\",\n    \"UNet Weight 1\": \"UNet 权重 1\",\n    \"UNet Weight 2\": \"UNet 权重 2\",\n    \"UNet Weight 3\": \"UNet 权重 3\",\n    \"UNet Weight 4\": \"UNet 权重 4\",\n    \"UNet Weight 5\": \"UNet 权重 5\",\n    \"Unfreeze seed\": \"不固定种子\",\n    \"Unified Predictor-Corrector Framework for Fast Sampling of Diffusion Models\": \"用于扩散模型快速采样的统一预测-校正框架\",\n    \"uniform\": \"均匀\",\n    \"UniPC lower order final\": \"最后几步采样应用低阶 UniPC 采样方法\",\n    \"UniPC order\": \"UniPC 低阶步数\",\n    \"UniPC Order\": \"UniPC 低阶步数\",\n    \"UniPC order (must be < sampling steps)\": \"UniPC 的预测校正次数 (需小于采样步数)\",\n    \"UniPC skip type\": \"UniPC 跳过类型\",\n    \"UniPC variant\": \"UniPC 变体\",\n    \"unknown\": \"未知\",\n    \"Unload\": \"卸载\",\n    \"Unload all interrogate models\": \"卸载所有反推模型\",\n    \"Unload all models from memory\": \"从内存中卸载所有模型\",\n    \"unload model\": \"卸载模型\",\n    \"Unload model after running\": \"反推完成后卸载模型\",\n    \"Unload models\": \"卸载模型\",\n    \"Unload SD checkpoint to free VRAM\": \"卸载 Stable Diffusion 模型以释放显存\",\n    \"Unload VAE and CLIP from VRAM when training\": \"训练时从显存中卸载 VAE 和 CLIP 模型\",\n    \"Unnecessary Javascript file\": \"多余的 Javascript 文件\",\n    \"unzip the file to\": \"将文件解压缩到\",\n    \"up\": \"上\",\n    \"Upcast cross attention layer to float32\": \"将交叉关注层向上转换到 float32\",\n    \"Upcast cross attention layer to FP32\": \"将交叉关注层向上转换到 FP32\",\n    \"update\": \"更新\",\n    \"Update\": \"更新\",\n    \"Update directory names in database\": \"更新数据库中的文件夹名字\",\n    \"Update installed extensions\": \"更新已安装扩展\",\n    \"update list\": \"更新列表\",\n    \"Update Mask\": \"更新蒙版\",\n    \"uploaded video FPS\": \"上传视频的帧率\",\n    \"uploaded video resolution\": \"上传视频的分辨率\",\n    \"uploaded video total frame count\": \"上传视频的总帧数\",\n    \"Upload mask\": \"上传蒙版图片\",\n    \"Upload mask image\": \"上传蒙版图片\",\n    \"Upload Mask to ControlNet Inpainting\": \"上传蒙版到 ControNet 重绘\",\n    \"Upload prompt inputs\": \"上传提示词输入文件\",\n    \"Upper Arm\": \"上臂长度\",\n    \"Upscale\": \"图像放大\",\n    \"Upscale Before Restoring Faces\": \"放大后再进行面部修复\",\n    \"Upscale by\": \"放大倍数\",\n    \"Upscale factor\": \"放大倍数\",\n    \"Upscale height\": \"放大高度\",\n    \"Upscale image with IMG2IMG\": \"通过图生图放大图像\",\n    \"Upscale model\": \"超分模型\",\n    \"Upscaler\": \"放大算法\",\n    \"upscaler 1\": \"放大算法 1\",\n    \"Upscaler 1\": \"放大算法 1\",\n    \"upscaler 2\": \"放大算法 2\",\n    \"Upscaler 2\": \"放大算法 2\",\n    \"Upscaler 2 vis.\": \"放大算法 2 可见程度\",\n    \"Upscaler 2 visibility\": \"放大算法 2 强度\",\n    \"Upscale ratio\": \"放大倍率\",\n    \"Upscale resize\": \"放大倍数\",\n    \"Upscaler for img2img\": \"图生图放大算法\",\n    \"*Upscale uploaded video*\": \"*放大已上传的视频*\",\n    \"Upscale width\": \"放大宽度\",\n    \"Upscaling\": \"放大\",\n    \"URL\": \"地址\",\n    \"URL for extension's git repository\": \"扩展的 git 仓库网址\",\n    \"Use\": \"使用 \",\n    \"Use alpha as mask\": \"启用透明度蒙版\",\n    \"Use an\": \"使用一个\",\n    \"Use an empty output directory to save pictures normally instead of writing to the output directory.\": \"输出图像到一个空目录，而非设置里指定的输出目录\",\n    \"Use another image as ControlNet input\": \"使用另外的图像输入 ControlNet\",\n    \"Use another image as mask\": \"使用另外的图像作为遮罩\",\n    \"Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition\": \"两步生成\\n以较小的分辨率生成初步图像后再放大\\n然后在不改变构图的情况下改善细节\",\n    \"Use BLIP for caption\": \"使用 BLIP 生成标签 (自然语言)\",\n    \"Use Control Net inpaint model\": \"使用 ControlNet 的 inpait 模型\",\n    \"Use CPU for SAM\": \"使用 CPU 进行 SAM 处理\",\n    \"Use CPU Only (SLOW)\": \"只用 CPU (很慢)\",\n    \"Use cross attention optimizations while training\": \"训练时开启 Cross Attention 优化\",\n    \"Use custom colors\": \"使用自定义颜色\",\n    \"Use custom DepthMap\": \"使用自定义深度图\",\n    \"Use deepbooru for caption\": \"使用 Deepbooru 生成标签\",\n    \"Use delta values for movement parameters\": \"使用增量值作为运动参数\",\n    \"Use Depth Map If exists in /video_key_depth\": \"使用深度图（如果存在/video_key_depth目录）\",\n    \"Use different seed for each picture\": \"为每张图片使用不同随机种子\",\n    \"Use dropdown for sampler selection instead of radio group\": \"采样器列表处使用下拉菜单取代单选框\",\n    \"Use dropout\": \"使用 dropout\",\n    \"Use EMA for finetuning\": \"使用 EMA 权重进行微调\",\n    \"use Face Crop img2img\": \"使用图生图脸部修复\",\n    \"Use Fast Mode(It will be faster, but the quality of the mask will be lower.)\": \"使用快速模式（它会更快，但蒙版质量会较低）。\",\n    \"Use half floats\": \"启用半精度浮点\",\n    \"Use init\": \"使用初始化\",\n    \"Use inpaint width/height\": \"启用自定义重绘宽高\",\n    \"Use input image's alpha channel as mask\": \"使用输入图像的透明度通道作为遮罩\",\n    \"Use Jit\": \"使用实时产出模式\",\n    \"Use local groundingdino to bypass C++ problem\": \"使用本地 Groundingdino 以绕过 C++ 问题\",\n    \"Use Lora in uc diffusion model\": \"在反向扩散模型中使用 LoRA\",\n    \"Use Lora in uc text model encoder\": \"在反向文本编码器中使用 LoRA\",\n    \"Use lossless compression for webp images\": \"对 WebP 图像使用无损压缩\",\n    \"Use LyCoris handler for all Lora types\": \"使用 LyCORIS 处理器加载所有 Lora 模型\",\n    \"Use main sampler\": \"使用文生图采样方法\",\n    \"Use mask\": \"使用蒙版\",\n    \"Use mask as output alpha channel\": \"使用遮罩作为透明度通道输出\",\n    \"Use mask video\": \"使用视频蒙版\",\n    \"use MBW\": \"使用分块合并\",\n    \"Use mid-control on highres pass (second pass)\": \"进行高分辨率修复时使用中间层控制 (mid-control)\",\n    \"Use minimal area for face selection\": \"用最小面积进行脸部选择\",\n    \"Use noise mask\": \"使用噪点蒙版\",\n    \"Use old emphasis implementation. Can be useful to reproduce old seeds.\": \"使用旧的强调符号解析器，可用于复现早期种子结果 (2022-09-29)\",\n    \"Use old karras scheduler sigmas (0.1 to 10).\": \"对于 Karras 调度器使用旧的 sigma 值范围 (0.1 - 10) (2023-01-01)\",\n    \"Use only-mid-control on high-res. fix (second pass)\": \"在高分辨率修复 (第二通道) 中仅使用中间层 (mid-control) 控制\",\n    \"Use optimized images in the thumbnail interface (significantly reduces the amount of data transferred)\": \"在缩略图界面中使用优化的图像 (显著减少传输数据量)\",\n    \"Use original name for output filename during batch process in extras tab\": \"在后期处理选项卡中的批量处理过程中，使用原始名称作为输出文件名\",\n    \"Use PNG alpha channel as loss weight\": \"使用 PNG 图片的透明通道作为 loss 权重\",\n    \"Use Preprocess image If exists in /controlnet_preprocess\": \"使用预处理图像（如果存在/controlnet_preprocess目录）\",\n    \"Use prompt from preview image\": \"一键使用本模型预览图所使用的提示词\",\n    \"Use random seeds for sub-generations when doing a rolling generation (WARNING!!! The result will be non-deterministic!!!)\": \"在进行梯度放大倍数生成时, 对子代生成应用随机种子 (警告!!! 图像结果随机无法复现!!!)\",\n    \"Use raw CLIP token to calculate token count (without emphasis or embeddings)\": \"使用原始 CLIP 词元数计算词元长度（不含 emphasis 或 embeddings）\",\n    \"Use recursive with glob pattern\": \"使用 glob 模式递归搜索\",\n    \"Use recycle bin when deleting images\": \"将删除的图片放入回收站而非直接彻底删除\",\n    \"Use regex\": \"使用正则表达式\",\n    \"User interface\": \"用户界面\",\n    \"username\": \"用户名\",\n    \"Username\": \"用户名\",\n    \"Uses aesthetic image scorer extension to check the quality of the image.\": \"使用 aesthetic image scorer (美学图像评分) 插件来检测图像质量\",\n    \"Use same random seed for all lines\": \"每行输入都使用同一个随机种子\",\n    \"Use same sampler\": \"使用相同采样方法\",\n    \"Use separate CFG scale\": \"使用独立的提示词引导系数\",\n    \"Use separate CFG scale 2nd\": \"使用独立的提示词引导系数\",\n    \"Use separate CFG scale 3rd\": \"使用独立的提示词引导系数\",\n    \"Use separate CFG scale 4th\": \"使用独立的提示词引导系数\",\n    \"Use separate CFG scale 5th\": \"使用独立的提示词引导系数\",\n    \"Use separate steps\": \"使用独立迭代步数\",\n    \"Use separate steps 2nd\": \"使用独立迭代步数\",\n    \"Use separate steps 3rd\": \"使用独立迭代步数\",\n    \"Use separate steps 4th\": \"使用独立迭代步数\",\n    \"Use separate steps 5th\": \"使用独立迭代步数\",\n    \"Use separate width/height\": \"使用独立重绘宽高\",\n    \"Use separate width/height 2nd\": \"使用独立重绘宽高\",\n    \"Use separate width/height 3rd\": \"使用独立重绘宽高\",\n    \"Use separate width/height 4th\": \"使用独立重绘宽高\",\n    \"Use separate width/height 5th\": \"使用独立重绘宽高\",\n    \"Use Smart-Steps\": \"优化迭代次数\",\n    \"Use Space Instead Of _\": \"使用 \\\"空格 \\\" 代替 \\\"下划线_\\\"\",\n    \"Use spaces instead of underscore\": \"使用空格代替下划线\",\n    \"Uses your\": \"使用你的\",\n    \"Use tags like [seed] and [date] to define how filenames for images are chosen. Leave empty for default.\": \"使用[seed]和[date]等标记来选择如何定义图像的文件名。留空使用默认值\",\n    \"Use tags like [seed] and [date] to define how subdirectories for images and grids are chosen. Leave empty for default.\": \"使用[seed]和[date]等标记来选择如何定义图像和网格的子目录。留空使用默认值\",\n    \"Use Text Escape\": \"使用文本转义\",\n    \"(use (text) to make model pay more attention to text and [text] to make it pay less attention)\": \"(使用 (提示词) 使模型更关注该文本, 使用 [提示词] 减少其关注度)\",\n    \"Use the negative_prompts field to automatically append all words as a negative prompt. *Don't* add --neg in the negative_prompts field!\": \"使用 negative_prompts 字段自动将所有单词附加为反向提示词，不要在 negative_prempts 字段中添加 --neg ！\",\n    \"Use this negative prompt\": \"使用此框填写的反向提示词\",\n    \"Use this when scanning can not find a local model on civitai\": \"无法通过扫描获取本地模型信息时使用此功能\",\n    \"Use Ultimate SD Upscale script instead\": \"使用 Ultimate SD Upscale 脚本作为替代\",\n    \"Use upscaler name as filename suffix in the extras tab\": \"后期处理时将超分算法名称添加到文件名后缀中\",\n    \"Use via API\": \"使用 via API\",\n    \"VAE Checkpoints to cache in RAM\": \"保留在内存中的 VAE 模型数量\",\n    \"Variation seed\": \"变异随机种子\",\n    \"Variation strength\": \"变异强度\",\n    \"Vectors\": \"向量\",\n    \"Vector Studio\": \"Vector Studio - 矢量工作室\",\n    \"verbose console output\": \"将详细信息输出到控制台\",\n    \"version\": \"版本\",\n    \"Version\": \"版本\",\n    \"Vertical\": \"垂直\",\n    \"Vertical Mirroring\": \"垂直镜像\",\n    \"vertical split num\": \"垂直分割数\",\n    \"Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resolution and extremely low quality.\": \"性能很好的近似值。与VAE相比速度非常快，但生成的图片的水平/垂直分辨率是VAE的八分之一，质量极低\",\n    \"vibrant\": \"vibrant (自然饱和度)\",\n    \"Vid2depth\": \"视频转深度\",\n    \"Video\": \"视频\",\n    \"Video Depth\": \"视频深度\",\n    \"Video Init\": \"视频初始化\",\n    \"Video init path\": \"初始化视频路径\",\n    \"video_init_path, extract_nth_frame, overwrite_extracted_frames\": \"初始视频路径, 提取第N帧, 覆盖提取帧\",\n    \"Video Input\": \"视频输入 \",\n    \"video_input mode only, enables the extraction and use of a separate video file intended for use as a mask. White areas of the extracted video frames will not be affected by diffusion, while black areas will be fully effected. Lighter/darker areas are affected dynamically.\": \"仅视频输入模式使用，提取和使用单独的视频文件作为蒙版。提取的视频帧的白色区域将不受生成器的影响，而黑色区域将完全受到影响。较亮/较暗的区域会受到动态影响。\",\n    \"Video mask path\": \"视频蒙版路径\",\n    \"Video output\": \"视频输出\",\n    \"Video Output Settings\": \"视频输出设置\",\n    \"Video to get Depth from\": \"从视频中获取深度\",\n    \"Video to Upscale\": \"待放大视频\",\n    \"Video Upscaling\": \"视频放大\",\n    \"View changes\": \"查看更改\",\n    \"View the wiki for usage tips.\": \"点击查看 Wiki 获取使用说明\",\n    \". Visit\": \" 分隔。查看\",\n    \"Visualize\": \"可视化预览\",\n    \"Visualize Cross-Attention\": \"Cross-Attention 可视化\",\n    \"Visual style\": \"视觉风格\",\n    \"vivid_light\": \"亮光\",\n    \"VRAM usage polls per second during generation.\": \"生成图像时, 每秒查询显存 (VRAM) 使用情况的次数\",\n    \"VRAM usage polls per second during generation. Set to 0 to disable.\": \"生成图像时，每秒查询显存 (VRAM) 使用情况的次数。设置为 0 可禁用\",\n    \"WARNING : Settings are immediately applied but will not be saved until you click \\\"Save\\\"\": \"警告：设置修改后会立即应用，但在点击“保存”之前不会被保存\",\n    \"WARNING : Some visual settings are immediately applied but will not be saved until you click \\\"Save\\\"\": \"警告: 部分视觉设置修改后会立即应用, 但在点击 ”保存“ 之前不会被保存\",\n    \"watercolor\": \"watercolor (水彩)\",\n    \"Waves color\": \"波形颜色\",\n    \"WebUI State\": \"WebUI 状态\",\n    \"Weight\": \"权重\",\n    \"Weight 1\": \"权重 1\",\n    \"Weight 2\": \"权重 2\",\n    \"Weight 3\": \"权重 3\",\n    \"Weight 4\": \"权重 4\",\n    \"Weight 5\": \"权重 5\",\n    \"Weighted sum\": \"加权和\",\n    \"Weights\": \"权重\",\n    \"weights alpha\": \"权重 α\",\n    \"Weights alpha\": \"权重 α\",\n    \"weights beta\": \"权重 β\",\n    \"Weights beta\": \"权重 β\",\n    \"Weights Presets\": \"权重预设\",\n    \"Weights setting\": \"权重设置\",\n    \"Weights Setting\": \"权重设置\",\n    \"Weight sum:A*(1-alpha)+B*alpha\": \"加权和: A*(1-α)+B*α\",\n    \"Weight values\": \"权重值\",\n    \"Weight_values\": \"权重值\",\n    \"What to put inside the masked area before processing it with Stable Diffusion.\": \"在使用 Stable Diffusion 处理蒙版区域前在其中放置什么\",\n    \"When adding extra network such as Hypernetwork or Lora to prompt, use this multiplier for it.\": \"当添加扩展模型 (如 Hypernetwork 或 Lora) 到提示词中时，默认使用此倍率。\",\n    \"When adding to prompt, refer to lora by\": \"在添加到提示词时，通过以下格式提及lora\",\n    \"When adding to prompt, refer to Lora by\": \"将扩展模型添加到提示词时，通过以下格式提及lora\",\n    \"when checked, do not output a video\": \"启用时, 不输出视频\",\n    \"when enabled, will re-extract video frames each run. When using video_input mode, the run will be instructed to write video frames to the drive. If you’ve already populated the frames needed, uncheck this box to skip past redundant extraction, and immediately start the render. If you have not extracted frames, you must run at least once with this box checked to write the necessary frames.\": \"启用时，将在每次运行时重新提取视频帧。使用video_input模式时，运行程序将视频帧写入驱动器。如果已经填充了所需的帧，请取消选中此框以跳过多余的提取，然后立即开始渲染。如果尚未提取帧，则必须在选中此框的情况下至少运行一次，以写入必要的帧。\",\n    \"When loading models attempt stream loading optimized for slow or network storage\": \"为低速硬盘或网络存储使用流式模型加载优化\",\n    \"When loading models attempt to reuse previous model dictionary\": \"加载模型时尝试复用上一模型的字典\",\n    \"(when reading generation parameters from text into UI)\": \"(适用于从文本中读取生成参数并应用到用户界面时)\",\n    \"(when reading generation parameters from text into UI))\": \"(适用于从文本中读取生成参数并应用到用户界面时)\",\n    \"When reading generation parameters from text into UI (from PNG info or pasted text), do not change the selected model/checkpoint.\": \"当从 PNG 图片信息或粘贴文本读取生成参数到用户界面时，不根据参数更改当前选定模型\",\n    \"When searched\": \"检索时\",\n    \"(\\\"When searched\\\" option will only show the item when the search string has 4 characters or more)\": \"(\\\"检索时\\\" 选项只有当搜索字符串有4个或更多字符时, 才会显示隐藏栏目)\",\n    \"when this box is checked, and FFMPEG mp4 is selected as the output format, an audio file will be multiplexed with the video.\": \"选中此框并以 FFMPEG mp4 为输出格式时, 音频文件将与视频复用\",\n    \"When using 'Save' button, only save a single selected image\": \"使用“保存”按钮时，只保存一个选定的图像\",\n    \"When using \\\"Save\\\" button, save images to a subdirectory\": \"使用 “保存” 按钮时，将图像保存到子目录\",\n    \"When you fill in the Overwrite subject field, that subject will be used to build the dynamic prompt around. It is best, if you set the subject type to match the subject. For example, set it to humanoid if you place a person in the override subject field.\": \"填写覆盖主题词段将被用来建立动态提示词。最好把主题类型设置为与主题相匹配。例如：如果你在覆盖主题词段中放置一个人，就把它设置为人形。\",\n    \"Whether to use optical flow to blend frames during cadence (if cadence more than 1)\": \"在生成间隔期间，使用光流法渲染帧（即使间隔大于1）\",\n    \"Which algorithm to use to produce the image\": \"使用哪种算法生成图像\",\n    \"whimsical\": \"whimsical (奇幻)\",\n    \"White is Opaque\": \"白色不透明\",\n    \"Whitelist\": \"白名单\",\n    \"Whole picture\": \"整张图片\",\n    \"wide\": \"wide (宽图)\",\n    \"width\": \"宽度\",\n    \"Width\": \"宽度\",\n    \"Width/height limit for the above option, in pixels\": \"上述选项的 宽/高 限制 (单位: 像素)\",\n    \"[wiki]\": \"[Wiki]\",\n    \"wiki\": \"Wiki\",\n    \"will do nothing!\": \"将不生效!\",\n    \"will output a greyscale depth map image alongside the output images.\": \"将与输出图像一起输出灰度深度图图像。\",\n    \"Will upscale the image by the selected scale factor; use width and height sliders to set tile size\": \"按照选定的比例放大图像；使用长/宽拖动条以设置分块大小\",\n    \"With confidence\": \"输出置信度权重\",\n    \"With img2img, do exactly the amount of steps the slider specifies.\": \"图生图时，准确执行滑块指定的迭代步数\",\n    \"With img2img, fill image's transparent parts with this color.\": \"在图生图中使用以下颜色填充透明区域\",\n    \"With Workflow mode, you turn off the automatic generation of new prompts on ‘generate’, and it will use the Workflow prompt field instead. So you can work and finetune any fun prompts without turning of the script.\": \"在工作流模式下，关闭了 \\\"生成 \\\"时自动生成新提示词的功能，它会使用工作流提示词作为代替。因此可以在不打开脚本的情况下工作和对有趣的提示词进行微调。\",\n    \"word masks\": \" \",\n    \"Workflow assist\": \"工作流协助\",\n    \"Workflow assist, suggestions by redditor Woisek.\": \"工作流协助，由 redditor: Woisek 提出。\",\n    \"Workflow mode, turns off prompt generation and uses below Workflow prompt instead.\": \"工作流模式：关闭提示词生成，使用以下的工作流提示词代替。\",\n    \"Workflow prompt\": \"工作流提示词\",\n    \"*Work In Progress*. All params below are going to be keyframable at some point. If you want to speedup the integration, join Deforum's development. \\uD83D\\uDE09\": \"*正在开发*. 下面的所有参数在某些点是关键的。如果你想加快集成，请加入 Deforum 的开发。\\uD83D\\uDE09\",\n    \"Write all generated prompts to a file\": \"将所有生成的提示词写入文件\",\n    \"Write image to a directory (default - log/images) and generation parameters into csv file.\": \"将图像写入目录（默认 - log/images）并将生成参数写入 csv 表格文件\",\n    \"write merged model ID to\": \"将融合模型 ID 写入到\",\n    \"x center axis for 2D angle/zoom *only*\": \"2D 旋转/缩放中 X 轴的中心点\",\n    \"xmenber\": \"X 值\",\n    \"X panning\": \"X 轴平移量\",\n    \"xtype\": \"X 类型\",\n    \"X type\": \"X 轴类型\",\n    \"X Types\": \"X 轴类型\",\n    \"X values\": \"X 轴值\",\n    \"X/Y plot\": \"X/Y 图表\",\n    \"X/Y/Z plot\": \"X/Y/Z 图表\",\n    \"XYZ plot\": \"XYZ 图\",\n    \"y center axis for 2D angle/zoom *only*\": \"2D 旋转/缩放中 Y 轴中心点\",\n    \"Yes\": \"是\",\n    \"ymenber\": \"Y 值\",\n    \"You can also choose the prompt seperator mode for use with Latent Couple extension\": \"可以选择提示词分隔模式来使用 Latent Couple 插件\",\n    \". You can also join this\": \". 你同样可以加入这个\",\n    \"You can change the maximum execution time, by default it’s 30seconds.\": \"你可以调节最大执行时间，默认 30 秒。\",\n    \"You can choose a certain subject type, if you want to generate something more specific. It has the following types:\": \"需要生成更具体的图像, 可以选择主题类型。有以下几种：\",\n    \"You can enhance semantic segmentation for control_v11p_sd15_seg from lllyasviel. Non-semantic segmentation for Edit-Anything will be supported when they convert their models to lllyasviel format.\": \"你可以使用 lllyasviel 的 control_v11p_sd15_seg 模型进行语义分割。当模型转换为 lllyasviel 格式时，将还将支持Edit-Anything 的非语义分割。\",\n    \"You can enhance semantic segmentation for control_v11p_sd15_seg from lllyasviel. You can also utilize\": \"可以使用 lllyasviel 的 control_v11p_sd15_seg 模型强化语义分割功能。也可以使用 \",\n    \"You can generate image layout either in single image or in batch. Since there might be A LOT of outputs, there is no gallery for preview. You need to go to the output folder for either single image or batch process.\": \"你可以生成单张或批量的图像分布。由于可能有大量图片输出，所以无法预览。你需要进入输出文件夹，查看和进行后续操作。\",\n    \"You can mask images by their categories via semantic segmentation. Please enter category ids (integers), separated by\": \"可通过语义分割将图像分类屏蔽。请输入类别ID (整数) , 以\",\n    \"You can mask images by their categories via semantic segmentation. Please enter category ids (integers), separated by +. Visit here for ade20k and here for coco to get category->id map. Note that coco jumps some numbers, so the actual ID is line_number - 21.\": \"你可以通过语义分割模型按类别创建蒙版。请输入类别 ID（整数），用+分隔。可以访问 [这里] 获取 ade20k 的分类列表，或者 [这里] 获取 coco 的分类列表。注意，coco 会略过一些数字，所以实际的 ID 是列表中编号 -21。\",\n    \"You can put any image or images or video you like in the background.\": \"你可以任何你喜欢的图像或者视频放在背景中。\",\n    \"You can put comma seperated values here, those will be ignored from any list processing. For example, adding \\\"\\\"film grain, sepia\\\"\\\", will make these values not appear during generation.\": \"可以填入用逗号隔开的提示词，这些提示词包含的值将会在所有列表处理中被忽略。例如，添加 “”film grain, sepia“” ，将会使得这些提示词包含的值在生成时不出现。\",\n    \"You can specify in this field -> [Ebsynth Utility]->[configuration]->[stage 8]->[Background source]\": \"你可以在这里设置 -> [Ebsynth Utility]->[插件配置]->[步骤 8]->[背景源]\",\n    \"You can specify \\\"path_to_project_dir/inv/crossfade_tmp\\\".\": \"可以将其设置为“你的工程目录/inv/crossfade_tmp”。\",\n    \"You can stop the algorithm at any time\": \"你可以在任意时间停止图像增强算法\",\n    \"You can toggle the separator mode. Standardly this is a comma, but you can choose an AND or a BREAK.\": \"可以切换提示词分隔符。标准设置应该为逗号，但现在可以选择 AND 或者 BREAK 。\",\n    \"You can try it by own, to dig more deeper into Abyss ...\": \"可自行探索，以窥深渊...\",\n    \"You can turn it off and maybe add your own in the prefix or suffix prompt fields\": \"可以关闭本选项，然后可以在前缀或后缀提示词段中添加自己想要指定的艺术家。\",\n    \"You can use this as a guided image tool or as a looper depending on your settings in the keyframe images field. \\n                                   Set the keyframes and the images that you want to show up. \\n                                   Note: the number of frames between each keyframe should be greater than the tweening frames.\": \"根据关键帧图像字段中的设置，可以将其用作引导图像工具或循环器。\\n设置要显示的关键帧和图像。\\n注意：每个关键帧之间的帧数应大于中间帧。\",\n    \"You can use this as a guided image tool or as a looper depending on your settings in the keyframe images field. \\n                               Set the keyframes and the images that you want to show up. \\n                               Note: the number of frames between each keyframe should be greater than the tweening frames.\": \"根据关键帧图像字段中的设置，可以将其用作引导图像工具或循环器。\\n设置要显示的关键帧和图像。\\n注意：每个关键帧之间的帧数应大于中间帧。\",\n    \"You may configurate automatic sam generation. \": \"你可以配置自动 SAM 的参数。\",\n    \"You may configurate automatic sam generation. See\": \"可以配置以下项目来自动 SAM 。查看\",\n    \"You may configurate the following items and generate masked image for all images under a directory. This mode is designed for generating LoRA/LyCORIS training set.\": \"配置以下项目，为目录下所有图像生成蒙版。该模式用于生成 LoRA / LyCORIS 训练集。\",\n    \"You must enter text prompts to enable groundingdino. Otherwise this extension will fall back to point prompts only.\": \"必须输入文本提示词才能启用 GroundingDINO，否则将仅使用标记点。\",\n    \"You probably want this to be 'fp16'.\": \"你可能想要设置为半精度 (fp16)。\",\n    \"Your Civitai API Key\": \"Civitai API 密钥\",\n    \"Your Civitai Link Key\": \"Civitai Link 密钥\",\n    \"Y panning\": \"Y 轴平移量\",\n    \"ytype\": \"Y 类型\",\n    \"Y type\": \"Y 轴类型\",\n    \"Y Types\": \"Y 轴类型\",\n    \"Y values\": \"Y 轴值\",\n    \"Y Values\": \"Y 轴值\",\n    \"Zip\": \"打包下载\",\n    \"ZoeDepth was not trained on panoramic images. It doesn't know anything about panoramas or spherical projection. Here, we just treat the estimated depth as radius and some projection errors are expected. Nonetheless, ZoeDepth still works surprisingly well on 360 reconstruction.\": \"ZoeDepth 不是基于全景图像上训练的。它无法识别全景图或球形投影的特征。在这个选项卡，它仅把估计的深度当作半径，所以会产生一些预料中的投影误差。尽管如此，ZoeDepth 在 360° 重建模型上仍有令人惊讶的效果。\",\n    \"ZoeDepth was not trained on panoramic images. It doesn’t know anything about panoramas or spherical projection. Here, we just treat the estimated depth as radius and some projection errors are expected. Nonetheless, ZoeDepth still works surprisingly well on 360 reconstruction.\": \"ZoeDepth 不是基于全景图像上训练的。它无法识别全景图或球形投影的特征。在这个选项卡，它仅把估计的深度当作半径，所以会产生一些预料中的投影误差。尽管如此，ZoeDepth 在 360° 重建模型上仍有令人惊讶的效果。\",\n    \"Zoom\": \"缩放参数\",\n    \"Zoom in masked area\": \"缩放遮罩区域\",\n    \"Z type\": \"Z 轴类型\",\n    \"Z values\": \"Z 轴值\"\n}\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <script src=\"index.js\"></script>\n    </head>\n    <style>\n        sp-textarea,\n        textarea {\n            width: 100%;\n            height: 100px;\n        }\n\n        #taPromptShortcut {\n            height: 300px;\n            margin: 3px auto;\n        }\n\n        #taPrompt {\n            box-sizing: border-box;\n            background: rgb(37, 37, 37);\n        }\n\n        .container {\n            width: 100%;\n            padding-left: 3%;\n            padding-right: 3%;\n        }\n\n        sp-progressbar {\n            margin-bottom: 3px;\n            margin-top: 3px;\n        }\n\n        .prompt-container {\n            width: 100%;\n            padding-left: 5%;\n            padding-right: 5%;\n        }\n\n        #collapsible {\n            background-color: #777;\n            color: white;\n            cursor: pointer;\n            padding: 5px;\n            width: 100%;\n            border: none;\n            text-align: left;\n            outline: none;\n            font-size: 15px;\n        }\n\n        #collapsible:hover {\n            background-color: #333;\n        }\n\n        .content {\n            padding: 0 18px;\n            /* display: none; */\n            overflow: hidden;\n        }\n\n        .grid-container {\n            display: inline-flex;\n            grid-template-columns: auto auto auto;\n        }\n\n        .column-item-image {\n            width: 100px;\n            height: 100px;\n            margin: 0;\n        }\n\n        .viewer-image,\n        .history-image,\n        .image-search {\n            width: 100px;\n            height: 100px;\n            margin: 0;\n            position: relative;\n            max-height: 100%;\n            max-width: 100%;\n        }\n\n        .viewer-image-button {\n            display: none;\n            /* background-color:  #495b79; */\n            color: white;\n            border: none;\n            cursor: pointer;\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            width: 100%;\n            /* height: 20px; */\n            margin: 0;\n            max-height: 100%;\n            max-width: 100%;\n        }\n\n        .viewer-image-container {\n            position: relative;\n            width: 100px;\n            height: 100px;\n            margin: 0;\n        }\n\n        .viewer-image-container:hover .viewer-image-button {\n            display: flex;\n        }\n\n        .viewer-image-container:hover .thumbnail-image-button {\n            display: flex;\n        }\n\n        .viewer-container {\n            display: flex;\n            flex-wrap: wrap;\n        }\n\n        .thumbnail-image-button {\n            display: none;\n            /* background-color:  #495b79; */\n            color: white;\n            border: none;\n            cursor: pointer;\n            position: absolute;\n            /* bottom: 0;\n            left: 0; */\n            width: 100%;\n            /* height: 20px; */\n            margin: 0;\n            max-height: 100%;\n            max-width: 100%;\n        }\n\n        .thumbnail-image-button:nth-child(2) {\n            border-color: green;\n            bottom: 0;\n            left: 0;\n        }\n        .thumbnail-image-button:nth-child(3) {\n            border-color: pink;\n            bottom: 0;\n            right: 0;\n        }\n        .thumbnail-image-button:nth-child(4) {\n            border-color: yellow;\n            top: 0;\n            left: 0;\n        }\n        .thumbnail-image-button:nth-child(5) {\n            border-color: red;\n            top: 0;\n            right: 0;\n        }\n\n        .column-item {\n            margin: 0;\n        }\n\n        .button-style {\n            background-color: #777;\n            color: white;\n            cursor: pointer;\n            width: 100px;\n            border: none;\n            text-align: left;\n            outline: none;\n            font-size: 15px;\n            margin: 0;\n        }\n\n        .disableBtn {\n            opacity: 0.65;\n            cursor: not-allowed !important;\n        }\n        .btnSquare,\n        #btnRefreshModels {\n            background-color: #777;\n            color: white;\n            cursor: pointer;\n            border: none;\n            text-align: left;\n            outline: none;\n            font-size: 15px;\n            margin: 0;\n        }\n        #btnRefreshModels:hover {\n            background-color: #333;\n        }\n        #btnRefreshModels:focus {\n            background-color: #f0f0f0;\n        }\n        .btnSquare:not(.btnGenerateClass):hover {\n            background-color: #333;\n        }\n        .btnSquare:focus {\n            background-color: #f0f0f0;\n        }\n        #btnUpdate {\n            background-color: #3555ac;\n            color: white;\n            cursor: pointer;\n\n            border: none;\n\n            text-align: left;\n            outline: none;\n            font-size: 15px;\n            margin-left: 3px;\n        }\n        #btnUpdate:hover {\n            background-color: #3f68d6;\n        }\n        .button-style2 {\n            background-color: #777;\n            color: white;\n            cursor: pointer;\n\n            border: 1px;\n\n            text-align: left;\n            outline-style: solid;\n            outline: solid;\n            font-size: 15px;\n            margin: 10px;\n        }\n\n        .wrapper {\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            /* overflow: auto; */\n            overflow-x: hidden;\n            overflow-y: scroll;\n            padding: 0;\n        }\n\n        #progressContainer {\n            display: flex;\n            justify-content: space-between;\n        }\n\n        #lVersionNumber {\n            display: flex;\n            margin-left: auto;\n        }\n\n        .flexContainer {\n            flex: 0 0 auto;\n            display: flex;\n            flex-direction: row;\n        }\n\n        #historySeedLabelContainer {\n            display: flex;\n            margin-left: auto;\n        }\n\n        #menu-bar-container {\n            width: 100%;\n            display: flex;\n            /* justify-content: space-between; */\n            margin: 3px auto;\n        }\n\n        #sdBtnContainer {\n            display: flex;\n            flex: 0 0 auto;\n\n            flex-direction: row;\n            justify-content: space-between;\n            margin-bottom: 2px;\n        }\n\n        .labelNumber {\n            color: aliceblue;\n        }\n\n        #lNameInpaintPdding {\n            margin-right: 10px;\n        }\n\n        #pProgressBar {\n            width: 150px;\n        }\n        /* tabs */\n        .sp-tabs {\n            flex: 0 0 auto;\n            display: flex;\n            flex-direction: row;\n            border-bottom: 2px solid #3e3e3e;\n            margin-left: 10px;\n            margin-right: 10px;\n        }\n\n        .sp-tab {\n            margin-right: 12px;\n        }\n\n        .sp-tab sp-label {\n            color: rgba(255, 255, 255, 0.75);\n        }\n\n        .sp-tab:hover sp-label {\n            color: white;\n        }\n\n        .sp-tab.selected {\n            border-bottom: 2px solid white;\n            margin-bottom: -2px;\n        }\n\n        .sp-tab.selected sp-label {\n            color: white;\n        }\n\n        @media (prefers-color-scheme: light), (prefers-color-scheme: lightest) {\n            .sp-tabs {\n                border-bottom: 2px solid #b8b8b8;\n            }\n\n            .sp-tab sp-label {\n                color: rgba(0, 0, 0, 0.66);\n            }\n\n            .sp-tab:hover sp-label {\n                color: black;\n            }\n\n            .sp-tab.selected {\n                border-bottom: 2px solid black;\n            }\n\n            .sp-tab.selected sp-label {\n                color: black;\n            }\n        }\n\n        .sp-tab-page {\n            display: none;\n            padding: 8px;\n            flex-direction: column;\n            max-width: 100%;\n            position: relative;\n        }\n\n        .sp-tab-page.visible {\n            display: flex;\n        }\n\n        .sp-tab-page > * {\n            flex: 0 0 auto;\n        }\n\n        .viewerImgSelected {\n            border: 3px solid #6db579;\n        }\n\n        .viewerImgActive {\n            border: 3px solid #fb9700;\n        }\n\n        .generate-more {\n            background-color: #6db579;\n        }\n\n        .generate {\n            background-color: #ff595e;\n        }\n\n        .connected {\n            color: #6db579;\n        }\n\n        .disconnected {\n            color: #ff595e;\n        }\n\n        #slWidth {\n            width: 50%;\n            margin-right: 10px;\n        }\n\n        #slHeight {\n            width: 50%;\n            margin-left: 10px;\n        }\n\n        #hrWidth {\n            width: 33%;\n            margin-right: 10px;\n        }\n\n        #hrHeight {\n            width: 33%;\n            margin-left: 10px;\n        }\n        #hrScaleSlider,\n        #hrDenoisingStrength {\n            width: 50%;\n            margin-left: 10px;\n        }\n\n        #tiNumberOfSteps {\n            width: 50%;\n            width: auto;\n        }\n\n        .rbMaskContent {\n            font-size: 1.1em;\n        }\n\n        #rbSelectionModeLabel,\n        .rbSelectionMode,\n        .rbBaseSize {\n            font-size: 1em;\n            margin-right: 12px;\n        }\n        #BackendTypeLabel,\n        .rbBackendType {\n            font-size: 1.05em;\n            margin-right: 12px;\n        }\n        .checkbox {\n            font-size: 1em;\n            margin-right: 10px;\n        }\n\n        #slCfgScale {\n            width: 50%;\n            margin-right: 10px;\n        }\n        #slImageCfgScale {\n            width: 100%;\n            margin-right: 10px;\n        }\n\n        #slDenoisingStrength {\n            width: 50%;\n            margin-left: 10px;\n        }\n\n        #slInpaintingMaskWeight {\n            width: 100%;\n            /* margin-left: 10px; */\n        }\n\n        .disabled-btn {\n            opacity: 0.65;\n            cursor: not-allowed;\n        }\n\n        .buttonImage {\n            padding: 8px 8px 8px 32px;\n            font-family: Arial, Verdana;\n            background: #f0f0f0\n                url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABfUlEQVQ4y42TP2tUQRTFf3PnPYiLIAiKiKhIsLbxS9hZaykWNmKjgqT0A6SxslRIFRsRv0QwdZB1YyGipImbzWbfnHst3sZdZF92Bw7D/LmH37nDpL1NAyAlHgDXWW18j+A9QBXTnQhu3H704TXS2aU5s/f2/qvTZeXx78goDdE0Z9anusYDmxn4zMAlYglBMsN9zkAzgxwrGGCGnLzIwELCVZbUG+oicDWoLOtBhZwcAQFUZd6gCC/dBPW5Hr+/7VPaCHci2DU5TJVDBe+Q5cyvwT4ucfdleS7noQdURfMEDd4Rwc04OvzDtfWbjCYTitpG/hehoI4IZhmpjTgcj09jUGmeQAVXB4EypbRxjk5O0JTAvgygOBSnap9xsUJC0/nx4BLFW3p78c7Z6SeOJ2ktvL2wUC7G4zHh4uBgxPEkre30Ewb0NrZ0+XDEeUtGXdULZckYDodYMp59vLD9eZftjS31EnARuPr0Xn6yfoVbq/zlrz/pb37SG+DHXyrMGdFXikHpAAAAAElFTkSuQmCC);\n            background-position: 8px 8px;\n            background-repeat: no-repeat;\n        }\n        .reverse_image_serach {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/image-search.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n        .search-button {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/search.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n\n            background-position: center;\n        }\n        .layerToSelection {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/layer_to_selection.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n        .linkSlider {\n            margin-top: 25px;\n            font-family: Arial, Verdana;\n            /* background-image: url(./icon/chain.svg); */\n            /* background-color: #777; */\n            background-color: transparent;\n\n            background-size: 20px;\n            width: 20px;\n            height: 20px;\n            background-repeat: no-repeat;\n        }\n        .whiteChain {\n            background-image: url(./icon/chain_white.svg);\n        }\n        .blackChain {\n            background-image: url(./icon/chain_black.svg);\n        }\n        .acceptAllImgBtn {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/accept_all.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n\n        .acceptSelectedImgBtn {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/accept_selected.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n\n        .discardAllImgBtn {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/discard_all.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n\n        .discardSelectedImgBtn {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/discard_selected.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n\n        .resetButton {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/reset_settings.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n\n        .snapshotButton {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/camera_icon.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n        .svgButton {\n            font-family: Arial, Verdana;\n\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n        .selectionAreaButton {\n            background-image: url(./icon/reselect-area.svg);\n        }\n        .interrogateButton {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/writing-icon.svg);\n            /* background-color: transparent; */\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n        .svg-buttons-container *:not(:last-child) {\n            margin-right: 3px;\n        }\n\n        .divBtn {\n            display: block;\n            padding: 10px;\n            border: 1px solid black;\n            background: red;\n            font-size: 16px;\n            color: black;\n            justify-content: center;\n            align-items: center;\n            border-radius: 5px;\n            display: flex;\n            flex-direction: column;\n            text-align: center;\n            padding: 15px;\n            margin: 5px;\n            cursor: pointer;\n        }\n        .line-divider {\n            background-color: #3e3e3e;\n        }\n        .res-increase {\n            color: #6db579;\n        }\n        .res-decrease {\n            color: #ff595e;\n        }\n        .controlNetImaageContainer {\n            margin-right: 3px;\n        }\n        #divInitImageViewerContainer {\n            display: flex;\n        }\n        .rbSubTab {\n            font-size: 0.9em;\n        }\n        .rbSubTab:last-child {\n            margin-right: 0;\n        }\n        #lexicaPrompt {\n            position: static;\n            top: 0;\n            left: 0;\n        }\n\n        .missing-error {\n            color: #ff595e;\n\n            white-space: normal;\n        }\n\n        .refreshButton {\n            font-family: Arial, Verdana;\n            background-image: url(./icon/reset_settings.svg);\n            background-color: #777;\n            background-size: 30px;\n            width: 30px;\n            height: 30px;\n            background-repeat: no-repeat;\n        }\n    </style>\n    <style>\n        .custom-menu {\n            display: flex;\n            list-style: none;\n            margin: 0;\n            padding: 0;\n        }\n        .custom-menu input[type='radio'] {\n            display: none;\n        }\n        .custom-menu label {\n            display: block;\n            padding: 10px;\n            cursor: pointer;\n        }\n        li input[type='radio']:checked + label {\n            border-bottom: 2px solid white;\n        }\n\n        li .sub-menu-tab-class + label {\n            color: rgba(255, 255, 255, 0.75);\n        }\n\n        li:hover .sp-menu-tab-class:hover + label {\n            color: white;\n        }\n\n        /* li .sp-tab.selected {\n            border-bottom: 2px solid white;\n            margin-bottom: -2px;\n        } */\n\n        /* .sp-tab.selected sp-label {\n            color: white;\n        } */\n    </style>\n    <style>\n        .second_panel {\n            flex: 1 1 auto;\n            /* overflow: scroll; */\n            overflow-y: scroll;\n            padding-left: 10px;\n            padding-right: 10px;\n            padding-top: 12px;\n            padding-bottom: 12px;\n            flex-direction: column;\n            height: 100%; /* Set a fixed height for the container */\n        }\n    </style>\n\n    <!-- searchable menu CSS -->\n    <style>\n        #mySearch {\n            width: 100%;\n            font-size: 18px;\n            padding: 5px;\n            color: white;\n            background-color: #222;\n            font-weight: bold;\n        }\n        #mySearch:focus {\n            border: 1px solid;\n            border-color: #7a97e4;\n        }\n        #myMenu {\n            list-style-type: none;\n            padding: 0;\n            margin: 0;\n            max-height: 150px;\n            overflow-y: scroll;\n            background-color: #222;\n        }\n        #myMenu li {\n            color: white;\n        }\n        #myMenu li a {\n            padding: 12px;\n            text-decoration: none;\n            color: white;\n            display: block;\n            font-weight: bold;\n        }\n        #myMenu li a:hover {\n            background-color: #333;\n        }\n    </style>\n\n    <body>\n        <!-- <sp-textarea id=\"tool_tip\" open placement=\"top\">use this when you want to fill empty areas of the canvas</sp-textarea> -->\n        <!-- <sp-tooltip id=\"tool_tip\" open placement=\"top\">use this when you want to fill empty areas of the canvas</sp-tooltip> -->\n\n        <div class=\"container wrapper\">\n            <div class=\"sp-tabs\">\n                <div\n                    class=\"sp-tab selected\"\n                    id=\"sp-stable-diffusion-ui-tab\"\n                    title=\"Stable Diffusion UI\"\n                >\n                    <sp-label>Stable Diffusion</sp-label>\n                </div>\n                <div class=\"sp-tab\" id=\"sp-viewer-tab\">\n                    <sp-label>Viewer</sp-label>\n                </div>\n                <div class=\"sp-tab\" id=\"sp-control_net-tab\">\n                    <sp-label>ControlNet</sp-label>\n                </div>\n\n                <div\n                    class=\"sp-tab\"\n                    id=\"sp-image_search-tab\"\n                    style=\"display: none\"\n                >\n                    <sp-label>Image Search</sp-label>\n                </div>\n\n                <div\n                    class=\"sp-tab\"\n                    id=\"sp-prompts-library-tab\"\n                    style=\"display: none\"\n                >\n                    <sp-label>Prompts library</sp-label>\n                </div>\n                <div class=\"sp-tab\" id=\"sp-horde-tab\">\n                    <sp-label>Horde</sp-label>\n                </div>\n                <div class=\"sp-tab\" id=\"sp-extras-tab\">\n                    <sp-label>Extras</sp-label>\n                </div>\n\n                <div class=\"sp-tab\" id=\"sp-settings-tab\">\n                    <sp-label>Settings</sp-label>\n                </div>\n                <div>\n                    <span\n                        class=\"disconnected\"\n                        id=\"automaticStatus\"\n                        title=\"'A' for Automatic1111 server (webui-user.bat), Green is connected. Red Means there is a problem with your Automatic1111. Run 'webui-user.bat' and hit 'Refresh' button \"\n                        >A</span\n                    >\n                    <span\n                        class=\"disconnected\"\n                        id=\"proxyServerStatus\"\n                        title=\"'P' for proxy server (start_server.bat), Green is connected. Red means you need to run 'start_server.bat' or hit Refresh button\"\n                        >P</span\n                    >\n                </div>\n                <sp-label slot=\"label\" id=\"lVersionNumber\">v0.0.0</sp-label>\n            </div>\n\n            <div class=\"sp-tab-page\" id=\"sp-viewer-tab-page\">\n                <div class=\"subTabOptionsContainer\">\n                    <div data-container-class=\"subTabOptionsContainer\">\n                        <ul id=\"viewer-sub-menu\" class=\"custom-menu\">\n                            <!-- <li>\n                                <input\n                                    type=\"radio\"\n                                    id=\"option1\"\n                                    name=\"options\"\n                                    checked\n                                    class=\"sub-menu-tab-class\"\n                                />\n                                <label for=\"option1\">Option 1</label>\n                            </li>\n                            <li>\n                                <input\n                                    type=\"radio\"\n                                    id=\"option2\"\n                                    name=\"options\"\n                                    class=\"sub-menu-tab-class\"\n                                />\n                                <label for=\"option2\">Option 2</label>\n                            </li>\n                            <li>\n                                <input\n                                    type=\"radio\"\n                                    id=\"option3\"\n                                    name=\"options\"\n                                />\n                                <label for=\"option3\">Option 3</label>\n                            </li> -->\n                        </ul>\n                        <sp-divider\n                            class=\"line-divider\"\n                            size=\"small\"\n                        ></sp-divider>\n                    </div>\n                    <sp-radio-group\n                        id=\"rgSubTab\"\n                        class=\"rbMaskContent\"\n                        data-container-class=\"subTabOptionsContainer\"\n                        style=\"display: none\"\n                    >\n                        <sp-radio\n                            title=\"\"\n                            class=\"rbSubTab\"\n                            checked\n                            value=\"viewer\"\n                            data-tab-name=\"sp-viewer-tab\"\n                            >Viewer</sp-radio\n                        >\n\n                        <sp-radio\n                            title=\"\"\n                            class=\"rbSubTab\"\n                            id=\"rbImageSearch\"\n                            data-tab-name=\"sp-image_search-tab\"\n                            value=\"image_search\"\n                            >Image Search</sp-radio\n                        >\n                        <sp-radio\n                            title=\"\"\n                            class=\"rbSubTab\"\n                            id=\"rbPromptsLibrary\"\n                            data-tab-name=\"sp-prompts-library-tab\"\n                            value=\"prompts-library\"\n                            >Prompts Library</sp-radio\n                        >\n                    </sp-radio-group>\n                </div>\n                <div id=\"viewerSubTab\">\n                    <div class=\"flexContainer\"></div>\n                    <div></div>\n\n                    <div class=\"\" id=\"divProgressImageViewerContainer\">\n                        <!-- <img\n                            class=\"\"\n                            id=\"progressImage\"\n                            src=\"https://source.unsplash.com/random\"\n                            style=\"width: 100px; height: 100px; max-width: 100%\"\n                        /> -->\n                    </div>\n                    <!-- <hr class=\"line-divider\" /> -->\n                    <sp-divider></sp-divider>\n\n                    <div class=\"\" id=\"divInitImageViewerContainer\">\n                        <!-- <img  class=\"viewer-image\" id=\"viewer_init_image_test\" data-metadata_json_string='{\"a\":1}' src='https://source.unsplash.com/random' /> -->\n                    </div>\n                    <!-- <hr class=\"line-divider\" /> -->\n                    <sp-divider></sp-divider>\n                    <div class=\"\" id=\"divInitMaskViewerContainer\">\n                        <!-- <img  class=\"viewer-image\" id=\"viewer_mask_test\" data-metadata_json_string='{\"a\":1}' src='https://source.unsplash.com/random' /> -->\n                    </div>\n                    <!-- <hr class=\"line-divider\" /> -->\n                    <sp-divider></sp-divider>\n                    <div class=\"viewer-container\" id=\"divViewerImagesContainer\">\n                        <!-- <img  class=\"viewer-image\" id=\"viewer_output_image_test\" data-metadata_json_string='{\"a\":1}' src='https://source.unsplash.com/random' /> -->\n                    </div>\n                </div>\n                <!-- </div> -->\n            </div>\n            <div class=\"sp-tab-page\" id=\"sp-control_net-tab-page\"></div>\n\n            <div class=\"sp-tab-page\" id=\"sp-image_search-tab-page\">\n                <div class=\"subTabOptionsContainer\"></div>\n\n                <div class=\"flexContainer\">\n                    <sp-label slot=\"label\">Image Search Engine</sp-label>\n                </div>\n                <div></div>\n                <div>\n                    <sp-textfield\n                        id=\"imageSearchField\"\n                        type=\"text\"\n                        placeholder=\"cute cats\"\n                        value=\"\"\n                        ><sp-label slot=\"label\">Search:</sp-label></sp-textfield\n                    >\n\n                    <button class=\"btnSquare\" id=\"btnImageSearch\">\n                        Image Search\n                    </button>\n                </div>\n                <div\n                    class=\"viewer-container\"\n                    id=\"divImageSearchImagesContainer\"\n                >\n                    <img\n                        class=\"history-image\"\n                        id=\"search_image_placeholder\"\n                        data-metadata_json_string='{\"a\":1}'\n                        src=\"https://source.unsplash.com/random\"\n                    />\n                </div>\n            </div>\n            <div class=\"sp-tab-page\" id=\"sp-prompts-library-tab-page\">\n                <div class=\"subTabOptionsContainer\"></div>\n                <sp-label slot=\"label\"\n                    >Prompt Shortcut: a single word that represent a\n                    prompt</sp-label\n                >\n                <div class=\"\">\n                    <sp-label slot=\"label\"\n                        >Key for new prompt shortcut</sp-label\n                    >\n                    <sp-textarea\n                        id=\"KeyPromptShortcut\"\n                        placeholder=\"to be replaced\"\n                        value=\"\"\n                    ></sp-textarea>\n                </div>\n                <div class=\"\">\n                    <sp-label slot=\"label\"\n                        >Value for new prompt shortcut</sp-label\n                    >\n                    <sp-textarea\n                        id=\"ValuePromptShortcut\"\n                        placeholder=\"to be replaced with\"\n                        value=\"\"\n                    ></sp-textarea>\n                    <button class=\"btnSquare\" id=\"btnUpdatePromptShortcut\">\n                        Add to Prompt Shortcut\n                    </button>\n                </div>\n                <div class=\"\">\n                    <sp-textarea\n                        id=\"taPromptShortcut\"\n                        placeholder=\"prompt shortcut\"\n                        value=\"\"\n                    ></sp-textarea>\n                </div>\n                <div>\n                    <sp-picker size=\"m\" label=\"Selection a prompt\">\n                        <sp-menu id=\"mPromptShortcutMenu\" slot=\"options\">\n                            <!-- <sp-menu-item> item </sp-menu-item> -->\n                        </sp-menu>\n                    </sp-picker>\n                    <button class=\"btnSquare\" id=\"btnRefreshPromptShortcutMenu\">\n                        Refresh Menu\n                    </button>\n                </div>\n                <div>\n                    <button class=\"btnSquare\" id=\"btnLoadPromptShortcut\">\n                        Load\n                    </button>\n                    <button class=\"btnSquare\" id=\"btnSavePromptShortcut\">\n                        Save\n                    </button>\n                </div>\n            </div>\n            <div class=\"sp-tab-page\" id=\"sp-horde-tab-page\">\n                <!-- Horde tab page -->\n                <div></div>\n                <div>\n                    <sp-label>Horde Key:</sp-label\n                    ><sp-textfield\n                        id=\"tiHordeApiKey\"\n                        type=\"password\"\n                        placeholder=\"0000000000\"\n                        value=\"\"\n                    ></sp-textfield>\n                    <button class=\"btnSquare\" id=\"btnSaveHordeSettings\">\n                        Save\n                    </button>\n                </div>\n\n                <sp-radio-group>\n                    <sp-label id=\"BackendTypeLabel\" slot=\"label\"\n                        >Select Backend:</sp-label\n                    >\n\n                    <!-- <sp-radio\n                        title=\"use the horde with the plugin no need to install anything else\"\n                        class=\"rbBackendType\"\n                        value=\"horde_native\"\n                        >Native Horde</sp-radio\n                    > -->\n                    <sp-radio\n                        title=\"Use the horde extension from Automatic1111 Extension tab\"\n                        class=\"rbBackendType\"\n                        value=\"auto1111_horde_extension\"\n                        >Auto1111 Horde Extension</sp-radio\n                    >\n                    <sp-radio\n                        title=\"use Auto1111 disable the Horde\"\n                        class=\"rbBackendType\"\n                        value=\"auto1111\"\n                        checked\n                        >Auto1111 Only</sp-radio\n                    >\n                    <!-- <sp-tooltip id=\"tool_tip\" open placement=\"top\">use this when you want to fill empty areas of the canvas</sp-tooltip> -->\n                </sp-radio-group>\n\n                <div id=\"menu-bar-container_horde\" style=\"display: flex\">\n                    <sp-picker size=\"m\" label=\"Selection type\">\n                        <sp-menu id=\"mModelsMenuHorde\" slot=\"options\">\n                            <!-- <sp-menu-item> item </sp-menu-item> -->\n                        </sp-menu>\n                    </sp-picker>\n\n                    <button class=\"btnSquare\" id=\"btnRefreshModelsHorde\">\n                        Refresh Models\n                    </button>\n                    <!-- <sp-label slot=\"label\"\n              id=\"lVersionNumber\">v0.0.0</sp-label> -->\n                </div>\n                <div>\n                    <sp-checkbox id=\"chUseNSFW\">NSFW</sp-checkbox>\n                    <sp-checkbox id=\"chUseSharedLaion\"\n                        >Share with LION</sp-checkbox\n                    >\n                    <sp-slider\n                        style=\"display: none\"\n                        show-value=\"true\"\n                        id=\"slSeedVariation\"\n                        min=\"1\"\n                        max=\"30\"\n                        value=\"1\"\n                    >\n                        <sp-label slot=\"label\">Seed variation:</sp-label>\n                    </sp-slider>\n                </div>\n            </div>\n            <div class=\"sp-tab-page\" id=\"sp-extras-tab-page\">\n                <div class=\"extraPageContainer\"></div>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n            </div>\n\n            <div class=\"sp-tab-page\" id=\"sp-settings-tab-page\">\n                <div>\n                    <sp-label>SD Url:</sp-label\n                    ><sp-textfield\n                        id=\"tiSdUrl\"\n                        type=\"text\"\n                        placeholder=\"http://127.0.0.1:7860\"\n                        value=\"\"\n                        style=\"width: 160px\"\n                    ></sp-textfield\n                    ><button\n                        class=\"btnSquare\"\n                        id=\"btnSdUrl\"\n                        style=\"margin-left: 5px\"\n                    >\n                        Submit\n                    </button>\n                    <button class=\"btnSquare\" id=\"btnSaveSettingsTabs\">\n                        Save\n                    </button>\n                </div>\n                <div id=\"settingsVAEContainer\"></div>\n                <div id=\"reactSettingsContainer\"></div>\n\n                <div>\n                    <sp-checkbox checked id=\"chUseOriginalPrompt\"\n                        >Restore Original Prompt</sp-checkbox\n                    >\n                </div>\n\n                <sp-checkbox checked id=\"chUseSilentMode\" style=\"display: none\"\n                    >Use Silent Mode</sp-checkbox\n                >\n                <sp-radio-group>\n                    <sp-label slot=\"label\"\n                        >Your PC Speed(optimization):</sp-label\n                    >\n                    <!-- <sp-label slot=\"label\">Select a Mode:</sp-label> -->\n                    <sp-radio title=\"\" class=\"rbPCSpeed\" value=\"slow\"\n                        >Slow PC</sp-radio\n                    >\n                    <sp-radio title=\"\" class=\"rbPCSpeed\" value=\"fast\" checked\n                        >Fast PC</sp-radio\n                    >\n\n                    <!-- <sp-tooltip id=\"tool_tip\" open placement=\"top\">use this when you want to fill empty areas of the canvas</sp-tooltip> -->\n                </sp-radio-group>\n                <!-- <a href=\"https://colab.research.google.com/drive/1nbcx_WOneRmYv9idBO33pN5CbxXrqZHu?usp=sharing\" target=\"_blank\">Don't have GPU, use Colab</a> -->\n                <sp-link\n                    href=\"https://colab.research.google.com/drive/1nbcx_WOneRmYv9idBO33pN5CbxXrqZHu?usp=sharing\"\n                    >Use Colab</sp-link\n                >\n\n                <div>\n                    <sp-textfield\n                        title=\"copy paste the address to access the folder where the images are stored\"\n                        id=\"tiDocPath\"\n                        type=\"text\"\n                        placeholder=\"\"\n                        value=\"\"\n                    >\n                        <sp-label slot=\"label\"\n                            >Folder Path (read only):</sp-label\n                        >\n                    </sp-textfield>\n                    <button class=\"btnSquare\" id=\"btnGetDocPath\">\n                        Get Path\n                    </button>\n                </div>\n            </div>\n\n            <div\n                class=\"sp-tab-page visible\"\n                id=\"sp-stable-diffusion-ui-tab-page\"\n            >\n                <div id=\"sdTabContainer\"></div>\n\n                <!-- stable diffusion tab page -->\n\n                <div class=\"\">\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div\n                        id=\"alwaysOnScriptsContainer\"\n                        style=\"margin-bottom: 10px\"\n                    ></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div style=\"margin-bottom: 3px\"></div>\n                    <div id=\"scriptsContainer\"></div>\n\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n\n                    <div class=\"reactViewerContainer\"></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div class=\"previewContainer\"></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div class=\"samContainer\"></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div class=\"oneButtonPromptContainer\"></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div id=\"PresetTabContainer\"></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <div id=\"ComfyUIContainer\"></div>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                    <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                </div>\n            </div>\n        </div>\n\n        <uxp-panel panelid=\"second_panel\">\n            <div id=\"search_second_panel\" class=\"container second_panel\">\n                <div class=\"previewContainer\"></div>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <div class=\"reactViewerContainer\"></div>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <div id=\"sp-control_net-tab-page2\"></div>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <div id=\"historyImagesContainer\"></div>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <div class=\"lexicaContainer\"></div>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <sp-divider class=\"line-divider\" size=\"large\"></sp-divider>\n                <!-- <div id=\"ComfyUIContainer\"></div> -->\n            </div>\n        </uxp-panel>\n\n        <uxp-panel panelid=\"toolbar\">\n            <div\n                id=\"toolbar_panel\"\n                class=\"_container\"\n                style=\"\n                    margin: 0;\n                    display: flex;\n                    justify-content: flex-start;\n                    /* padding-bottom: 5px; */\n                    flex-direction: column;\n                \"\n            >\n                <div\n                    style=\"\n                        margin: 0;\n                        display: flex;\n                        justify-content: flex-start;\n                        /* padding: 1px; */\n                        flex-direction: column;\n                    \"\n                >\n                    <div id=\"toolbarGenerateButtonsContainer\"></div>\n                    <div id=\"viewerButtonContainer\"></div>\n                    <div id=\"toolBarContainer\"></div>\n                </div>\n            </div>\n        </uxp-panel>\n        <div>\n            <!-- icon only svg button -->\n            <sp-action-button\n                id=\"svg_sp_btn\"\n                style=\"\n                    padding: 0;\n                    max-width: 32px;\n                    max-height: 32px;\n                    display: none;\n                \"\n            >\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg viewBox=\"0 0 36 36\" style=\"width: 18px; height: 18px\">\n                        <path\n                            d=\"M33.567 8.2L27.8 2.432a1.215 1.215 0 0 0-.866-.353H26.9a1.371 1.371 0 0 0-.927.406L5.084 23.372a.99.99 0 0 0-.251.422L2.055 33.1c-.114.377.459.851.783.851a.251.251 0 0 0 .062-.007c.276-.063 7.866-2.344 9.311-2.778a.972.972 0 0 0 .414-.249l20.888-20.889a1.372 1.372 0 0 0 .4-.883 1.221 1.221 0 0 0-.346-.945zM11.4 29.316c-2.161.649-4.862 1.465-6.729 2.022l2.009-6.73z\"\n                        />\n                    </svg>\n                </div>\n            </sp-action-button>\n\n            <!-- icon with svg button -->\n            <sp-action-button style=\"display: none\">\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg viewBox=\"0 0 36 36\" style=\"width: 18px; height: 18px\">\n                        <path\n                            d=\"M33.567 8.2L27.8 2.432a1.215 1.215 0 0 0-.866-.353H26.9a1.371 1.371 0 0 0-.927.406L5.084 23.372a.99.99 0 0 0-.251.422L2.055 33.1c-.114.377.459.851.783.851a.251.251 0 0 0 .062-.007c.276-.063 7.866-2.344 9.311-2.778a.972.972 0 0 0 .414-.249l20.888-20.889a1.372 1.372 0 0 0 .4-.883 1.221 1.221 0 0 0-.346-.945zM11.4 29.316c-2.161.649-4.862 1.465-6.729 2.022l2.009-6.73z\"\n                        />\n                    </svg>\n                </div>\n                Edit Text\n            </sp-action-button>\n            <sp-action-button\n                id=\"svg_sp_btn_datadownload\"\n                style=\"\n                    padding: 0;\n                    max-width: 32px;\n                    max-height: 32px;\n                    display: none;\n                \"\n            >\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg viewBox=\"0 0 18 18\" style=\"width: 18px; height: 18px\">\n                        <path\n                            d=\"M5.3885,12.5895a1.211,1.211,0,0,1-.314-.8C3.2305,11.478,1.509,10.942,1,10.135V14.5C1,15.8805,4.582,17,9,17c.1385,0,.2735-.0045.4105-.0065Z\"\n                        />\n                        <path\n                            d=\"M16.5,6.5V9.3635A1.18,1.18,0,0,0,17,8.5V5.135A5.06144,5.06144,0,0,1,14.3855,6.5Z\"\n                        />\n                        <path\n                            d=\"M6.315,10.5H8.5V7.13C5.953,7.059,1.8365,6.4625,1,5.135V8.5c0,.996,1.868,1.8535,4.565,2.255A1.21847,1.21847,0,0,1,6.315,10.5Z\"\n                        />\n                        <path\n                            d=\"M17.573,12.427A.25.25,0,0,0,17.3965,12H15V8H10v4H7.6035a.25.25,0,0,0-.1765.427L12.5,18Z\"\n                        />\n                    </svg>\n                </div>\n            </sp-action-button>\n            <!-- <img width=\"15px\" height=\"15px\" src=\"./icon/ftcopy.svg\">   -->\n\n            <sp-action-button\n                id=\"svg_sp_btn_search\"\n                style=\"\n                    padding: 0;\n                    max-width: 32px;\n                    max-height: 32px;\n                    display: none;\n                \"\n            >\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg viewBox=\"0 0 36 36\" style=\"width: 18px; height: 18px\">\n                        <path\n                            d=\"M31.5,28.9l-7.4-7.4c1.8-2.3,2.9-5.2,2.9-8.4c0-7.2-5.8-13-13-13S1,6.3,1,13.5s5.8,13,13,13c3.2,0,6.1-1.1,8.4-2.9l7.4,7.4 c0.4,0.4,0.9,0.6,1.5,0.6s1.1-0.2,1.5-0.6C32.3,31.1,32.3,29.7,31.5,28.9z M14,22c-4.7,0-8.5-3.8-8.5-8.5S9.3,5,14,5s8.5,3.8,8.5,8.5 S18.7,22,14,22z\"\n                        />\n                    </svg>\n                </div>\n                <!-- Search -->\n            </sp-action-button>\n            <sp-action-button\n                id=\"svg_sp_btn_canvas\"\n                style=\"\n                    padding: 0;\n                    max-width: 32px;\n                    max-height: 32px;\n                    display: none;\n                \"\n            >\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg\n                        version=\"1.0\"\n                        xmlns=\"http://www.w3.org/2000/svg\"\n                        width=\"18.000000pt\"\n                        height=\"18.000000pt\"\n                        viewBox=\"0 0 127.000000 127.000000\"\n                        preserveAspectRatio=\"xMidYMid meet\"\n                        style=\"\n                            width: 32px;\n                            height: 27px;\n                            position: absolute;\n                            top: 3px;\n                            left: -1px;\n                        \"\n                    >\n                        <g\n                            transform=\"translate(0.000000,115.000000) scale(0.100000,-0.100000)\"\n                            fill=\"#000000\"\n                            stroke=\"none\"\n                        >\n                            <path\n                                d=\"M577 1172 c-10 -11 -17 -36 -17 -60 l0 -42 -133 0 c-117 0 -136 -2\n-150 -18 -15 -16 -17 -49 -17 -254 l0 -236 -24 -6 c-53 -13 -74 -67 -38 -99\n15 -13 39 -17 115 -17 53 0 97 -4 97 -9 0 -5 -13 -69 -30 -143 -35 -155 -36\n-169 -12 -191 45 -41 84 -11 104 78 l13 60 150 0 150 0 13 -60 c15 -67 35 -95\n67 -95 27 0 55 29 55 56 0 11 -13 78 -30 150 -16 71 -30 135 -30 142 0 9 26\n12 98 12 83 0 102 3 115 18 33 36 14 85 -39 98 l-24 6 0 238 c0 217 -2 238\n-18 253 -15 14 -42 17 -150 17 l-132 0 0 43 c0 30 -6 49 -18 60 -26 23 -94 22\n-115 -1z m393 -377 l0 -235 -335 0 -335 0 0 235 0 235 335 0 335 0 0 -235z\nm77 -291 c3 -9 0 -20 -8 -25 -18 -11 -790 -11 -808 0 -8 5 -11 16 -8 25 6 14\n49 16 412 16 363 0 406 -2 412 -16z m-293 -133 c9 -39 16 -75 16 -80 0 -7 -47\n-11 -135 -11 -88 0 -135 4 -135 11 0 5 7 41 16 80 l16 69 103 0 103 0 16 -69z\"\n                            />\n                        </g>\n                    </svg>\n                </div>\n            </sp-action-button>\n\n            <sp-action-button\n                id=\"svg_sp_btn_preview\"\n                style=\"\n                    padding: 0;\n                    max-width: 32px;\n                    max-height: 32px;\n                    display: none;\n                \"\n            >\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg\n                        version=\"1.0\"\n                        xmlns=\"http://www.w3.org/2000/svg\"\n                        width=\"512.000000pt\"\n                        height=\"512.000000pt\"\n                        viewBox=\"0 0 512.000000 512.000000\"\n                        preserveAspectRatio=\"xMidYMid meet\"\n                        style=\"\n                            width: 32px;\n                            height: 32px;\n                            position: absolute;\n                            top: 0px;\n                            left: -1px;\n                        \"\n                    >\n                        <g\n                            transform=\"translate(0.000000,512.000000) scale(0.100000,-0.100000)\"\n                            fill=\"#000000\"\n                            stroke=\"none\"\n                        >\n                            <path\n                                d=\"M920 4311 c-118 -36 -212 -129 -259 -254 -18 -50 -21 -79 -21 -217\nl0 -160 80 0 80 0 0 128 c0 147 14 208 60 264 51 62 99 78 231 78 63 0 131 3\n152 6 l37 7 0 78 0 79 -167 -1 c-93 0 -179 -4 -193 -8z\"\n                            />\n                            <path\n                                d=\"M3840 4242 l0 -79 38 -7 c20 -3 88 -6 151 -6 132 0 180 -16 231 -78\n46 -56 60 -117 60 -264 l0 -128 80 0 80 0 0 158 c0 131 -3 169 -19 215 -36\n104 -104 182 -204 234 -50 27 -58 28 -234 31 l-183 4 0 -80z\"\n                            />\n                            <path\n                                d=\"M2450 3404 c-252 -30 -471 -107 -694 -243 -199 -122 -420 -320 -578\n-519 -32 -40 -58 -79 -58 -85 0 -20 105 -146 213 -256 296 -302 597 -483 937\n-562 122 -29 364 -37 495 -16 318 51 613 200 903 457 102 90 249 249 310 334\nl32 44 -47 62 c-67 90 -253 281 -358 368 -248 208 -538 351 -802 397 -90 16\n-290 27 -353 19z m279 -317 c189 -54 340 -214 386 -409 79 -338 -192 -670\n-549 -669 -158 0 -278 47 -390 151 -123 116 -177 238 -178 400 0 161 54 284\n178 400 153 143 345 187 553 127z\"\n                            />\n                            <path\n                                d=\"M2485 2841 c-59 -17 -86 -31 -129 -71 -153 -141 -103 -397 92 -471\n116 -43 262 -7 333 82 46 59 62 106 63 184 0 52 -6 82 -23 117 -27 55 -94 121\n-148 143 -45 19 -146 28 -188 16z\"\n                            />\n                            <path\n                                d=\"M640 1280 c0 -138 3 -167 21 -217 40 -107 103 -178 202 -230 50 -27\n58 -28 235 -31 l182 -4 0 80 0 79 -37 7 c-21 3 -89 6 -152 6 -132 0 -180 16\n-231 78 -46 56 -60 117 -60 264 l0 128 -80 0 -80 0 0 -160z\"\n                            />\n                            <path\n                                d=\"M4320 1312 c0 -147 -14 -208 -60 -264 -51 -62 -99 -78 -231 -78 -63\n0 -131 -3 -151 -6 l-38 -7 0 -79 0 -80 183 4 c176 3 184 4 234 31 99 52 162\n123 202 230 18 50 21 79 21 217 l0 160 -80 0 -80 0 0 -128z\"\n                            />\n                        </g>\n                    </svg>\n                </div>\n            </sp-action-button>\n\n            <sp-action-button\n                id=\"svg_sp_btn_expand\"\n                style=\"\n                    padding: 0;\n                    max-width: 32px;\n                    max-height: 32px;\n                    display: none;\n                \"\n            >\n                <div slot=\"icon\" style=\"fill: currentColor\">\n                    <svg\n                        version=\"1.0\"\n                        xmlns=\"http://www.w3.org/2000/svg\"\n                        width=\"200.000000pt\"\n                        height=\"200.000000pt\"\n                        viewBox=\"0 0 200.000000 200.000000\"\n                        preserveAspectRatio=\"xMidYMid meet\"\n                        style=\"\n                            width: 28px;\n                            height: 32px;\n                            position: absolute;\n                            top: -1px;\n                            left: 1px;\n                        \"\n                    >\n                        <g\n                            transform=\"translate(0.000000,200.000000) scale(0.100000,-0.100000)\"\n                            fill=\"#000000\"\n                            stroke=\"none\"\n                        >\n                            <path\n                                d=\"M246 1775 c-11 -6 -23 -21 -27 -35 -9 -31 -9 -275 0 -315 9 -41 50\n-61 89 -43 26 13 27 17 30 97 l3 84 178 -176 c123 -123 184 -177 200 -177 12\n0 33 11 46 25 14 13 25 34 25 46 0 16 -54 77 -177 200 l-176 178 84 3 c80 3\n84 4 97 31 11 22 11 32 0 55 l-13 27 -170 5 c-104 3 -177 1 -189 -5z\"\n                            />\n                            <path\n                                d=\"M1406 1775 c-32 -16 -43 -58 -22 -89 16 -26 18 -26 146 -26 l129 0 3\n-132 3 -133 28 -13 c22 -11 32 -11 55 0 l27 13 3 179 c2 120 -1 183 -9 192\n-14 17 -332 25 -363 9z\"\n                            />\n                            <path\n                                d=\"M1515 1600 c-11 -4 -84 -73 -162 -152 -153 -155 -162 -170 -118 -213\n43 -44 58 -36 219 124 132 131 149 153 149 181 0 22 -7 39 -22 52 -25 20 -36\n21 -66 8z\"\n                            />\n                            <path\n                                d=\"M700 783 c-8 -3 -93 -82 -187 -177 l-173 -171 0 82 c0 78 -2 84 -26\n99 -32 22 -73 10 -92 -26 -18 -35 -13 -330 7 -354 12 -14 36 -16 195 -14 l181\n3 13 28 c11 22 11 32 0 55 -13 26 -17 27 -98 30 l-84 3 174 174 c153 153 173\n177 173 206 0 47 -40 77 -83 62z\"\n                            />\n                            <path\n                                d=\"M1252 780 c-28 -12 -45 -52 -33 -82 5 -13 84 -97 175 -188 l166 -165\n-82 -5 c-78 -5 -84 -6 -96 -33 -11 -22 -11 -32 0 -55 l13 -27 181 -3 c146 -2\n183 0 193 12 8 9 11 67 9 192 l-3 178 -28 16 c-24 13 -30 13 -55 0 -26 -15\n-27 -20 -30 -100 l-3 -84 -172 171 c-95 94 -181 173 -192 176 -11 3 -30 1 -43\n-3z\"\n                            />\n                        </g>\n                    </svg>\n                </div>\n            </sp-action-button>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "index.js",
    "content": "// import {helloHelper} from 'helper.js'\n// helloHelper2 = require('./helper.js')\n// for organizational proposes\n// let g_sdapi_path = 'sdapi'\nconst g_image_not_found_url =\n    'https://images.unsplash.com/source-404?fit=crop&fm=jpg&h=800&q=60&w=1200'\nconst _log = console.log\nconst _warn = console.warn\nconst _error = console.error\nlet g_timer_value = 300 // temporary global variable for testing the timer pause function\nlet g_version =\n    'v' +\n    JSON.parse(require('fs').readFileSync('plugin:manifest.json', 'utf-8'))\n        .version\nlet g_sd_url = 'http://127.0.0.1:7860'\nlet g_online_data_url =\n    'https://raw.githubusercontent.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/master/utility/online_data.json'\nconst Jimp = require('./jimp/browser/lib/jimp.min')\nconst Enum = require('./enum')\nconst helper = require('./helper')\n\nconst sdapi = require('./sdapi_py_re')\n\n// const exportHelper = require('./export_png')\n\nconst psapi = require('./psapi')\nconst app = window.require('photoshop').app\nconst constants = require('photoshop').constants\nconst { batchPlay } = require('photoshop').action\nconst { executeAsModal } = require('photoshop').core\nconst dialog_box = require('./dialog_box')\n// const {entrypoints} = require('uxp')\nconst { sd_tab_store } = require('./typescripts/dist/bundle')\nconst html_manip = require('./utility/html_manip')\n// const export_png = require('./export_png')\n\nconst selection = require('./selection')\nconst layer_util = require('./utility/layer')\nconst sd_options = require('./utility/sdapi/options')\n// const sd_config = require('./utility/sdapi/config')\nconst session = require('./utility/session')\nconst { getSettings } = require('./utility/session')\n\nconst script_horde = require('./utility/sd_scripts/horde')\nconst prompt_shortcut = require('./utility/sdapi/prompt_shortcut')\nconst formats = require('uxp').storage.formats\nconst storage = require('uxp').storage\nconst shell = require('uxp').shell\nconst fs = storage.localFileSystem\nconst horde_native = require('./utility/sdapi/horde_native')\n\nconst dummy = require('./utility/dummy')\nconst general = require('./utility/general')\nconst thumbnail = require('./thumbnail')\nconst note = require('./utility/notification')\n\nconst settings_tab = require('./utility/tab/settings')\n//load tabs\n\nconst image_search_tab = require('./utility/tab/image_search_tab')\n\n// const share_tab = require('./utility/tab/share_tab')\nconst api = require('./utility/api')\n\nconst {\n    scripts,\n    main,\n    after_detailer_script,\n    control_net,\n    logger,\n    toJS,\n    viewer,\n    viewer_util,\n    preview,\n    // session_ts,\n    session_store,\n    progress,\n    sd_tab_ts,\n    // sd_tab_store,\n    sam,\n    settings_tab_ts,\n    one_button_prompt,\n    enum_ts,\n    multiPrompts,\n    ui_ts,\n    preset,\n    preset_util,\n    // dialog_box,\n    sd_tab_util,\n    node_fs,\n    io_ts,\n    extra_page,\n    selection_ts,\n    stores,\n    lexica,\n    api_ts,\n    comfyui,\n    comfyui_util,\n    comfyui_main_ui,\n\n    comfyapi,\n} = require('./typescripts/dist/bundle')\n\nconst io = require('./utility/io')\n\nfunction setLogMethod(should_log_to_file = true) {\n    let timer_id\n    if (should_log_to_file) {\n        console.log = (data, ...optional_param) => {\n            try {\n                _log(data, ...optional_param)\n\n                // const error = new Error({ data, ...optional_param });\n                const formattedOutput = logger.formateLog(\n                    data,\n                    ...optional_param\n                )\n                io.IOLog.saveLogToFile({ log: formattedOutput }, 'log.txt')\n            } catch (e) {\n                _warn('error while logging: ')\n                _warn(e)\n            }\n        }\n\n        console.warn = (data, ...optional_param) => {\n            try {\n                _warn(data, ...optional_param)\n                const error = new Error()\n                const stackTrace = error.stack\n                const formattedOutput = logger.formateLog(\n                    data,\n                    ...optional_param\n                )\n                io.IOLog.saveLogToFile(\n                    { warning: formattedOutput, stackTrace },\n                    'log.txt'\n                )\n            } catch (e) {\n                _warn('error while logging: ')\n                _warn(e)\n            }\n        }\n\n        console.error = (data, ...optional_param) => {\n            try {\n                _error(data, ...optional_param)\n                const error = new Error()\n                const stackTrace = error.stack\n                const formattedOutput = logger.formateLog(\n                    data,\n                    ...optional_param\n                )\n                io.IOLog.saveLogToFile(\n                    { error: formattedOutput, stackTrace },\n                    'log.txt'\n                )\n            } catch (e) {\n                _error('error while logging: ')\n                _error(e)\n            }\n        }\n    } else {\n        console.log = _log\n        console.warn = _warn\n        console.error = _error\n    }\n}\nsetLogMethod(settings_tab_ts.store.data.should_log_to_file)\n\n// const {\n//     script_args,\n//     script_name,\n// } = require('./ultimate_sd_upscaler/dist/ultimate_sd_upscaler')\n\nlet g_horde_generator = new horde_native.hordeGenerator()\nlet g_automatic_status = Enum.AutomaticStatusEnum['Offline']\n\nlet g_current_batch_index = 0\nlet g_is_laso_inapint_mode = true\n//REFACTOR: move to session.js\nasync function hasSessionSelectionChanged() {\n    try {\n        const isSelectionActive = await psapi.checkIfSelectionAreaIsActive()\n        if (isSelectionActive) {\n            const current_selection = isSelectionActive // Note: don't use checkIfSelectionAreaIsActive to return the selection object, change this.\n\n            if (\n                await hasSelectionChanged(\n                    current_selection,\n                    g_generation_session.selectionInfo\n                )\n            ) {\n                return true\n            } else {\n                //selection has not changed\n                return false\n            }\n        }\n    } catch (e) {\n        console.warn(e)\n        return false\n    }\n}\n\nasync function calcWidthHeightFromSelection(selectionInfo) {\n    //set the width and height, hrWidth, and hrHeight using selection info and selection mode\n    const selection_mode = sd_tab_store.data.selection_mode\n    if (selection_mode === 'ratio') {\n        //change (width and height) and (hrWidth, hrHeight) to match the ratio of selection\n        const base_size = sd_tab_util.helper_store.data.base_size\n        const [width, height, hr_width, hr_height] =\n            await selection.selectionToFinalWidthHeight(\n                selectionInfo,\n                base_size,\n                base_size\n            )\n        // console.log('width,height: ', width, height)\n        html_manip.autoFillInWidth(width)\n        html_manip.autoFillInHeight(height)\n        html_manip.autoFillInHRWidth(hr_width)\n        html_manip.autoFillInHRHeight(hr_height)\n    } else if (selection_mode === 'precise') {\n        const [width, height, hr_width, hr_height] = [\n            selectionInfo.width,\n            selectionInfo.height,\n            0,\n            0,\n        ]\n        html_manip.autoFillInWidth(width)\n        html_manip.autoFillInHeight(height)\n    }\n}\n//REFACTOR: rename to newSelectionEventHandler and move to session.js\nconst eventHandler = async (event, descriptor) => {\n    try {\n        console.log(event, descriptor)\n        const new_selection_info = await psapi.getSelectionInfoExe()\n        session_store.updateProperty(\n            'current_selection_info',\n            new_selection_info\n        )\n\n        // const isSelectionActive = await psapi.checkIfSelectionAreaIsActive()\n        if (new_selection_info) {\n            await calcWidthHeightFromSelection(new_selection_info)\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n//REFACTOR: move to generation_settings.js\nfunction getCurrentGenerationModeByValue(value) {\n    for (let key in generationMode) {\n        if (\n            generationMode.hasOwnProperty(key) &&\n            generationMode[key] === value\n        ) {\n            return key\n        }\n    }\n    return undefined\n}\n\nrequire('photoshop').action.addNotificationListener(\n    ['set', 'move', 'addTo', 'subtractFrom'],\n    eventHandler\n)\n//REFACTOR: move to document.js\nasync function getUniqueDocumentId() {\n    console.warn(\n        'getUniqueDocumentId is deprecated, instead use the methods in IOFolder'\n    )\n    try {\n        let uniqueDocumentId = await psapi.readUniqueDocumentIdExe()\n\n        console.log(\n            'getUniqueDocumentId():  uniqueDocumentId: ',\n            uniqueDocumentId\n        )\n\n        // Regular expression to check if string is a valid UUID\n        const regexExp =\n            /^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$/gi\n\n        // String with valid UUID separated by dash\n        // const str = 'a24a6ea4-ce75-4665-a070-57453082c256'\n\n        const isValidId = regexExp.test(uniqueDocumentId) // true\n        console.log('isValidId: ', isValidId)\n        if (isValidId == false) {\n            let uuid = self.crypto.randomUUID()\n            console.log(uuid) // for example \"36b8f84d-df4e-4d49-b662-bcde71a8764f\"\n            await psapi.saveUniqueDocumentIdExe(uuid)\n            uniqueDocumentId = uuid\n        }\n        return uniqueDocumentId\n    } catch (e) {\n        console.warn('warning Document Id may not be valid', e)\n    }\n}\n\n// attach event listeners for tabs\n//REFACTOR: move to html_manip.js (?) - if there is no business logic here and it's only for UI.\nArray.from(document.querySelectorAll('.sp-tab')).forEach((theTab) => {\n    theTab.onclick = () => {\n        try {\n            // localStorage.setItem(\"currentTab\", theTab.getAttribute(\"id\"));\n            Array.from(document.querySelectorAll('.sp-tab')).forEach((aTab) => {\n                if (aTab.getAttribute('id') === theTab.getAttribute('id')) {\n                    aTab.classList.add('selected')\n                } else {\n                    aTab.classList.remove('selected')\n                }\n            })\n            Array.from(document.querySelectorAll('.sp-tab-page')).forEach(\n                (tabPage) => {\n                    if (\n                        tabPage\n                            .getAttribute('id')\n                            .startsWith(theTab.getAttribute('id'))\n                    ) {\n                        tabPage.classList.add('visible')\n                    } else {\n                        tabPage.classList.remove('visible')\n                    }\n                }\n            )\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n})\n\n// entrypoints.setup({\n\n//   panels:{\n//     vanilla: ()=>{\n//       console.log(\"you are in the vanilla panel\")\n//     },\n//     experimental_1: ()=>{\n//       console.log(\"you are in the experimental_1 panel\")\n\n//     }\n//   }\n// }\n//   )\n// just a number that shouldn't unique enough that we will use when save files.\n// each session will get a number from 1 to 1000000\n//REFACTOR: move to session.js\nconst random_session_id = Math.floor(Math.random() * 1000000 + 1)\n//REFACTOR: move to helpers.js (or other utility file)\nfunction getSelectedText() {\n    // JavaScript\n    //     // Obtain the object reference for the <textarea>\n    // const txtarea = document.getElementById(\"taPrompt\");\n    const promptTextarea = document.querySelector('#taPrompt')\n    console.log('promptTextarea: ', promptTextarea.value)\n    //     // Obtain the index of the first selected character\n    var start = promptTextarea.selectionStart\n    console.log('start: ', start)\n    //     // Obtain the index of the last selected character\n    //     var finish = txtarea.selectionEnd;\n    //     console.log(\"finish: \",finish)\n\n    //     // Obtain the selected text\n    //     var sel = txtarea.value.substring(start, finish);\n    //     console.log(\"selected textarea: \", sel)\n\n    // Do something with the selected content\n}\n//REFACTOR: move to helpers.js\n// setInterval(getSelectedText,2000)\nfunction getCommentedString() {\n    // const text = document.getElementById(\"taPrompt\").value\n    // let text = `Visit /*W3Schools\n    // cute, girl, painterly\n    // *\\\\ any text\n    // and prompt`;\n    // let text = `cute cat /*by greg\n\n    // and artgerm\n\n    //  */ and famous artist`\n    let text = `Visit /*W3Schools \n  cute, girl, painterly   \n  */ any text\n  and prompt\n\n\n\n\n cute cat  /*by greg \n\n  and artgerm \n  \n   */ and famous artist`\n    console.log('getCommentedString: text: ', text)\n\n    // let pattern = /(\\/)(\\*)(\\s|\\S)*\\*\\\\/g;\n    let pattern = /(\\/)(\\*)(\\s|\\S)*?(\\*\\/)/g\n\n    let result = text.match(pattern)\n    console.log('getCommentedString: ', result)\n}\n\n//REFACTOR: move to the notfication.js\nasync function displayNotification(automatic_status) {\n    if (automatic_status === Enum.AutomaticStatusEnum['RunningWithApi']) {\n        //do nothing\n    } else if (\n        g_automatic_status === Enum.AutomaticStatusEnum['RunningNoApi']\n    ) {\n        await note.Notification.webuiAPIMissing()\n    } else if (g_automatic_status === Enum.AutomaticStatusEnum['Offline']) {\n        await note.Notification.webuiIsOffline()\n    }\n}\n//REFACTOR: move to sdapi.js\nasync function checkAutoStatus() {\n    try {\n        const options = await g_sd_options_obj.getOptions()\n        if (options) {\n            //means both automatic1111 and proxy server are online\n            html_manip.setAutomaticStatus('connected', 'disconnected')\n\n            g_automatic_status = Enum.AutomaticStatusEnum['RunningWithApi']\n\n            const extension_url = py_re.getExtensionUrl()\n            const full_url = `${extension_url}/heartbeat`\n            const heartbeat = (await api.requestGet(full_url))?.heartbeat\n\n            if (heartbeat) {\n                html_manip.setProxyServerStatus('connected', 'disconnected')\n                session_store.data.auto_photoshop_sd_extension_status = true\n            } else {\n                html_manip.setProxyServerStatus('disconnected', 'connected')\n                g_automatic_status =\n                    Enum.AutomaticStatusEnum['AutoPhotoshopSDExtensionMissing']\n                session_store.data.auto_photoshop_sd_extension_status = false\n            }\n            // html_manip.setProxyServerStatus('connected','disconnected')\n        } else {\n            html_manip.setAutomaticStatus('disconnected', 'connected')\n\n            if (await sdapi.isWebuiRunning()) {\n                //running with no api\n                g_automatic_status = Enum.AutomaticStatusEnum['RunningNoApi']\n                // await note.Notification.webuiAPIMissing()\n            } else {\n                //not running and of course no api\n                g_automatic_status = Enum.AutomaticStatusEnum['Offline']\n                // await note.Notification.webuiIsOffline()\n            }\n\n            return g_automatic_status\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n    return g_automatic_status\n}\n\n//REFACTOR: move to helper.js\nfunction promptShortcutExample() {\n    let prompt_shortcut_example = {\n        game_like:\n            'Unreal Engine, Octane Render, arcane card game ui, hearthstone art style, epic fantasy style art',\n        large_building_1: 'castle, huge building, large building',\n        painterly_style_1:\n            'A full portrait of a beautiful post apocalyptic offworld arctic explorer, intricate, elegant, highly detailed, digital painting, artstation, concept art, smooth, sharp focus, illustration',\n        ugly: '((((ugly)))), (((duplicate))), ((morbid)), ((mutilated)), out of frame, extra fingers, mutated hands, ((poorly drawn hands)), ((poorly drawn face)), (((mutation))), (((deformed))), ((ugly)), blurry, ((bad anatomy)), (((bad proportions))), ((extra limbs)), cloned face, (((disfigured))), out of frame, ugly, extra limbs, (bad anatomy), gross proportions, (malformed limbs), ((missing arms)), ((missing legs)), (((extra arms))), (((extra legs))), mutated hands, (fused fingers), (too many fingers), (((long neck)))',\n    }\n    var JSONInPrettyFormat = JSON.stringify(\n        prompt_shortcut_example,\n        undefined,\n        7\n    )\n    document.getElementById('taPromptShortcut').value = JSONInPrettyFormat\n    return prompt_shortcut_example\n}\n\n//**********Start: global variables\nlet prompt_dir_name = ''\nlet gImage_paths = []\nlet g_image_path_to_layer = {}\nlet g_init_images_dir = './server/python_server/init_images'\n//REFACTOR: move to generationSettings.js\ngCurrentImagePath = ''\n\n// let g_init_mask_layer;\n//REFACTOR: move to generationSettings.js\n\n// let g_mask_related_layers = {}\n// let g_init_image_related_layers = {}\n//REFACTOR: move to generationSettings.js, Note: numberOfImages deprecated global variable\n// let numberOfImages = document.querySelector('#tiNumberOfImages').value\n//REFACTOR: move to generationSettings.js\n\n//REFACTOR: move to generationSettings.js\nlet g_sd_sampler = 'Euler a'\n//REFACTOR: move to generationSettings.js\nlet g_denoising_strength = 0.7\n\nlet g_models = []\n// let g_models_horde = []\nlet g_model_title = ''\n// let gWidth = 512\n// let gHeight = 512\n//REFACTOR: move to generationSettings.js\nlet hWidth = 512\n//REFACTOR: move to generationSettings.js\nlet hHeight = 512\n//REFACTOR: move to generationSettings.js\nlet h_denoising_strength = 0.7\n// let g_inpainting_fill = 0\n// let g_last_outpaint_layers = []\n// let g_last_inpaint_layers = []\n// let g_last_snap_and_fill_layers = []\n\n//REFACTOR: move to generationSettings.js\nlet g_metadatas = []\n\n//REFACTOR: move to generationSettings.js\nlet g_can_request_progress = true\nlet g_saved_active_layers = []\nlet g_saved_active_selection = {}\nlet g_is_active_layers_stored = false\n\nlet g_number_generation_per_session = 0\nlet g_isViewerMenuDisabled = false // disable the viewer menu and viewerImage when we're importing images into the current document\nlet g_b_mask_layer_exist = false // true if inpaint mask layer exist, false otherwise.\nlet g_inpaint_mask_layer\nlet g_inpaint_mask_layer_history_id //store the history state id when creating a new inpaint mask layer\n\n// let g_selection = {}\n//REFACTOR: move to session.js\nlet g_selection = {}\nlet g_b_use_smart_object = true // true to keep layer as smart objects, false to rasterize them\nlet g_sd_options_obj = new sd_options.SdOptions()\n\nlet g_controlnet_max_models\n\nlet g_generation_session = new session.GenerationSession(0) //session manager\ng_generation_session.deactivate() //session starte as inactive\n\nlet g_ui_settings_object = ui_ts.getUISettingsObject()\nlet g_batch_count_interrupt_status = false\nconst requestState = {\n    Generate: 'generate',\n    Interrupt: 'interrupt',\n}\n\nlet g_request_status = '' //\n\n//REFACTOR: move to Enum.js\nconst generationMode = {\n    Txt2Img: 'txt2img',\n    Img2Img: 'img2img',\n    Inpaint: 'inpaint',\n    Outpaint: 'outpaint',\n    Upscale: 'upscale',\n}\nconst backendTypeEnum = {\n    Auto1111: 'auto1111',\n    HordeNative: 'horde_native',\n    Auto1111HordeExtension: 'auto1111_horde_extension',\n}\n\ng_generation_session.mode = generationMode['Txt2Img']\n\n//********** End: global variables */\n\ndocument\n    .getElementById('sp-extras-tab')\n    .addEventListener('click', async (evt) => {\n        try {\n            sd_tab_store.updateProperty('mode', 'upscale')\n\n            await postModeSelection() // do things after selection\n        } catch (e) {\n            console.warn(e)\n        }\n    })\n//REFACTOR: move to events.js\ndocument\n    .getElementById('sp-stable-diffusion-ui-tab')\n    .addEventListener('click', async (evt) => {\n        try {\n            sd_tab_store.updateProperty('mode', sd_tab_store.data.rb_mode)\n\n            await postModeSelection() // do things after selection\n        } catch (e) {\n            console.warn(e)\n        }\n    })\n//REFACTOR: move to psapi.js\nasync function createTempInpaintMaskLayer() {\n    if (!g_b_mask_layer_exist) {\n        //make new layer \"Mask -- Paint White to Mask -- temporary\"\n\n        const name = 'Mask -- Paint White to Mask -- temporary'\n        await psapi.unselectActiveLayersExe() // so that the mask layer get create at the top of the layer stocks\n        const top_layer_doc = await app.activeDocument.layers[0]\n        g_inpaint_mask_layer = await layer_util.createNewLayerExe(name, 60)\n        await executeAsModal(async () => {\n            await g_inpaint_mask_layer.moveAbove(top_layer_doc)\n        })\n        // g_inpaint_mask_layer.opacity = 50\n        g_b_mask_layer_exist = true\n        const index = app.activeDocument.historyStates.length - 1\n        g_inpaint_mask_layer_history_id =\n            app.activeDocument.historyStates[index].id\n        console.log(\n            'g_inpaint_mask_layer_history_id: ',\n            g_inpaint_mask_layer_history_id\n        )\n    }\n}\n//REFACTOR: move to psapi.js\nasync function deleteTempInpaintMaskLayer() {\n    console.log(\n        'g_inpaint_mask_layer_history_id: ',\n        g_inpaint_mask_layer_history_id\n    )\n    const historyBrushTools = app.activeDocument.historyStates\n        .slice(-10)\n        .filter(\n            (h) =>\n                h.id > g_inpaint_mask_layer_history_id &&\n                h.name === 'Brush Tool'\n        )\n    console.log(historyBrushTools)\n    if (historyBrushTools.length === 0 && g_b_mask_layer_exist) {\n        await layer_util.deleteLayers([g_inpaint_mask_layer])\n\n        g_b_mask_layer_exist = false\n    }\n}\n//REFACTOR: move to ui.js\nasync function postModeSelection() {\n    try {\n        if (sd_tab_store.data.rb_mode === generationMode['Inpaint']) {\n            //check if the we already have created a mask layer\n            await createTempInpaintMaskLayer()\n        } else {\n            // if we switch from inpaint mode, delete the mask layer\n            // Find all history states after the creation of the inpaint mask and their name brush tool\n            await deleteTempInpaintMaskLayer()\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//REFACTOR: move to events.js\ndocument.addEventListener('mouseenter', async (event) => {\n    try {\n        //only check if the generation mode has not changed( e.g a session.mode === img2img and the current selection is \"img2img\"  ).\n        // changing the mode will trigger it's own procedure, so doing it here again is redundant\n        if (\n            g_generation_session.isActive() &&\n            g_generation_session.mode === sd_tab_store.data.rb_mode\n        ) {\n            //if the generation session is active and the selected mode is still the same as the generation mode\n\n            console.log('hover on window')\n\n            const new_selection = await psapi.getSelectionInfoExe() //get the current active selection if there is any\n\n            if (\n                new_selection &&\n                (await hasSelectionChanged(\n                    new_selection,\n                    g_generation_session.selectionInfo\n                ))\n            ) {\n                // if there is an active selection and if the selection has changed\n\n                await calcWidthHeightFromSelection(new_selection)\n            } else {\n                // sessionStartHtml(true)//generate more, green color\n                //if you didn't move the selection.\n            }\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n})\n\n// function showLayerNames () {\n//   const app = window.require('photoshop').app\n//   const allLayers = app.activeDocument.layers\n//   const allLayerNames = allLayers.map(\n//     layer => `${layer.name} (${layer.opacity} %)`\n//   )\n\n//   const sortedNames = allLayerNames.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n//   document.getElementById('layers').innerHTML = `\n//         <ul>${sortedNames.map(name => `<li>${name}</li>`).join('')}</ul>`\n// }\n//REFACTOR: move to psapi.js\nfunction selectTool() {\n    var doc = app.activeDocument\n    var activeTool = app.currentTool\n\n    // if (activeTool !== toolName) {\n    //   toolName = activeTool;\n    //   doc.activeTool = toolName;\n    // }\n    // const util = require('util')\n\n    // console.log(util.inspect(myObject, {showHidden: false, depth: null, colors: true}))\n    console.dir(app, { depth: null })\n    console.log('hello this is Abdullah')\n    document.getElementById('layers').innerHTML = `<span>\n    selectTool was called, ${activeTool}\n    </span>`\n\n    //rectanglemarquee\n    // await require('photoshop').core.executeAsModal(newNormalLayer);\n}\n\n// User picks an image file\n// open a explorer for user to select a image file\n//REFACTOR: move to psapi.js\nasync function fillImage() {\n    const storage = require('uxp').storage\n    const fs = storage.localFileSystem\n    let imageFile = await fs.getFileForOpening({\n        types: storage.fileTypes.images,\n    })\n\n    // Create ImageFill for this image\n    const ImageFill = require('scenegraph').ImageFill\n    let fill = new ImageFill(imageFile)\n\n    // Set fill of first selected item\n    selection.items[0].fill = fill\n}\n// fillImage()\n//REFACTOR: move to psapi.js\nfunction pastImage2Layer() {\n    const { batchPlay } = require('photoshop').action\n    const { executeAsModal } = require('photoshop').core\n\n    executeAsModal(\n        () => {\n            // batchPlay([command], {})\n            const result = batchPlay(\n                [\n                    {\n                        _obj: 'paste',\n                        antiAlias: {\n                            _enum: 'antiAliasType',\n                            _value: 'antiAliasNone',\n                        },\n                        as: {\n                            _class: 'pixel',\n                        },\n                        _options: {\n                            dialogOptions: 'dontDisplay',\n                        },\n                    },\n                ],\n                {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                }\n            )\n        },\n        {\n            commandName: 'Create Label',\n        }\n    )\n}\n//REFACTOR: move to ui.js\nfunction sliderToResolution(sliderValue) {\n    return sliderValue * 64\n}\n\n//REFACTOR: move to psapi.js\n//store active layers only if they are not stored.\nasync function storeActiveLayers() {\n    setTimeout(async () => {\n        const layers = await app.activeDocument.activeLayers\n        console.log('storeActiveLayers: ', layers.length)\n\n        if (layers.length > 0) {\n            g_saved_active_layers = layers\n            await psapi.unselectActiveLayersExe()\n        }\n    }, 200)\n\n    // if (g_is_active_layers_stored == false) {\n    //   g_saved_active_layers = await app.activeDocument.activeLayers\n    //   g_is_active_layers_stored = true\n    //   await psapi.unselectActiveLayersExe()\n    // } else {\n    // }\n}\n//REFACTOR: move to psapi.js\nasync function restoreActiveLayers() {\n    const layers = await app.activeDocument.activeLayers\n    console.log('restoreActiveLayers: ', layers.length)\n    if (layers.length == 0) {\n        await psapi.selectLayersExe(g_saved_active_layers)\n        g_saved_active_layers = []\n    }\n    // if (g_is_active_layers_stored == true) {\n    //   // g_saved_active_layers = await app.activeDocument.activeLayers\n    //   await psapi.selectLayersExe(g_saved_active_layers)\n    //   g_is_active_layers_stored = false\n    //   g_saved_active_layers = []\n    // }\n}\n\n//store active selection only if they are not stored.\n//REFACTOR: move to psapi.js\nasync function storeActiveSelection() {\n    try {\n        setTimeout(async () => {\n            const layers = await app.activeDocument.activeLayers\n            const current_selection = await psapi.checkIfSelectionAreaIsActive()\n            console.log('storeActiveSelection: ', current_selection)\n\n            if (current_selection) {\n                g_saved_active_selection = current_selection\n                await psapi.unSelectMarqueeExe()\n            }\n        }, 200)\n    } catch (e) {\n        console.warn(e)\n    }\n}\n//REFACTOR: move to psapi.js\nasync function restoreActiveSelection() {\n    try {\n        const current_selection = await psapi.checkIfSelectionAreaIsActive()\n\n        console.log('restoreActiveSelection: ', current_selection)\n        if (\n            !current_selection &&\n            psapi.isSelectionValid(g_saved_active_selection)\n        ) {\n            await psapi.reSelectMarqueeExe(g_saved_active_selection)\n            g_saved_active_selection = {}\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//REFACTOR: unused, remove?\nfunction updateMetadata(new_metadata) {\n    const metadatas = []\n    try {\n        for (metadata of new_metadata) {\n            metadata_json = JSON.parse(metadata)\n            console.log('metadata_json:', metadata_json)\n            metadatas.push(metadata_json)\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n    return metadatas\n}\n\n//REFACTOR: move to selection.js\nasync function hasSelectionChanged(new_selection, old_selection) {\n    if (\n        new_selection.left === old_selection.left &&\n        new_selection.bottom === old_selection.bottom &&\n        new_selection.right === old_selection.right &&\n        new_selection.top === old_selection.top\n    ) {\n        return false\n    } else {\n        return true\n    }\n}\n\n//REFACTOR: move to ui.js\nfunction updateProgressBarsHtml(new_value) {\n    document.querySelectorAll('.pProgressBars').forEach((el) => {\n        // id = el.getAttribute(\"id\")\n        // console.log(\"progressbar id:\", id)\n        el.setAttribute('value', new_value)\n    })\n    document.querySelectorAll('.lProgressLabel').forEach((el) => {\n        console.log('updateProgressBarsHtml: ', new_value)\n        if (new_value > 0) el.innerHTML = 'In progress...'\n        else el.innerHTML = 'No work in progress'\n    })\n    // document.querySelector('#pProgressBar').value\n}\n\n//REFACTOR: move to psapi.js\nfunction _base64ToArrayBuffer(base64) {\n    var binary_string = window.atob(base64)\n    var len = binary_string.length\n    var bytes = new Uint8Array(len)\n    for (var i = 0; i < len; i++) {\n        bytes[i] = binary_string.charCodeAt(i)\n    }\n    return bytes.buffer\n}\n//REFACTOR: move to psapi.js\nfunction _arrayBufferToBase64(buffer) {\n    var binary = ''\n    var bytes = new Uint8Array(buffer)\n    var len = bytes.byteLength\n    for (var i = 0; i < len; i++) {\n        binary += String.fromCharCode(bytes[i])\n    }\n    return window.btoa(binary)\n}\n\n//REFACTOR: move to io.js\nasync function getDocFolder(doc_uuid) {\n    try {\n        // const uuid = await getUniqueDocumentId()\n        const data_folder = await storage.localFileSystem.getDataFolder()\n\n        let doc_folder\n        try {\n            doc_folder = await data_folder.getEntry(doc_uuid)\n        } catch (e) {\n            console.warn(e)\n            //create document folder\n            doc_folder = await data_folder.createFolder(doc_uuid)\n        }\n\n        return doc_folder\n    } catch (e) {\n        console.warn(e)\n    }\n}\n//REFACTOR: move to document.js\nasync function getCurrentDocFolder() {\n    //move to a global utililty lib\n    const uuid = await getUniqueDocumentId()\n\n    let doc_folder = await getDocFolder(uuid)\n    return doc_folder\n}\n//REFACTOR: move to document.js\nasync function getInitImagesDir() {\n    const uuid = await getUniqueDocumentId()\n\n    let doc_folder = await getDocFolder(uuid)\n    let init_folder\n    try {\n        init_folder = await doc_folder.getEntry('init_images')\n    } catch (e) {\n        console.warn(e)\n        //create document folder\n        init_folder = await doc_folder.createFolder('init_images')\n    }\n    return init_folder\n}\n\n//REFACTOR: move to document.js\nasync function base64ToFile(b64Image, image_name = 'output_image.png') {\n    // const b64Image =\n    //     'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'\n    try {\n        const img = _base64ToArrayBuffer(b64Image)\n\n        const img_name = image_name\n\n        const folder = await storage.localFileSystem.getTemporaryFolder()\n        const file = await folder.createFile(img_name, { overwrite: true })\n\n        await file.write(img, { format: storage.formats.binary })\n\n        const token = await storage.localFileSystem.createSessionToken(file) // batchPlay requires a token on _path\n\n        let place_event_result\n        let imported_layer\n        await executeAsModal(async () => {\n            const result = await batchPlay(\n                [\n                    {\n                        _obj: 'placeEvent',\n                        // ID: 6,\n                        null: {\n                            _path: token,\n                            _kind: 'local',\n                        },\n                        freeTransformCenterState: {\n                            _enum: 'quadCenterState',\n                            _value: 'QCSAverage',\n                        },\n                        offset: {\n                            _obj: 'offset',\n                            horizontal: {\n                                _unit: 'pixelsUnit',\n                                _value: 0,\n                            },\n                            vertical: {\n                                _unit: 'pixelsUnit',\n                                _value: 0,\n                            },\n                        },\n                        _isCommand: true,\n                        _options: {\n                            dialogOptions: 'dontDisplay',\n                        },\n                    },\n                ],\n                {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                }\n            )\n            console.log('placeEmbedd batchPlay result: ', result)\n\n            place_event_result = result[0]\n            imported_layer = await app.activeDocument.activeLayers[0]\n        })\n        return imported_layer\n    } catch (e) {\n        console.warn(e)\n    }\n\n    // return place_event_result\n}\n//REFACTOR: move to psapi.js\nasync function placeImageB64ToLayer(image_path, entery) {\n    //silent importer\n\n    try {\n        const formats = require('uxp').storage.formats\n        const storage = require('uxp').storage\n        const fs = storage.localFileSystem\n\n        const names = image_path.split('/')\n        const length = names.length\n        const image_name = names[length - 1]\n        const project_name = names[length - 2]\n        let pluginFolder = await fs.getPluginFolder()\n\n        const image_dir = `./server/python_server/output/${project_name}`\n        // image_path = \"output/f027258e-71b8-430a-9396-0a19425f2b44/output- 1674323725.126322.png\"\n\n        let img_dir = await pluginFolder.getEntry(image_dir)\n        // const file = await img_dir.createFile('output- 1674298902.0571606.png', {overwrite: true});\n\n        const file = await img_dir.createFile(image_name, { overwrite: true })\n\n        const img = await file.read({ format: formats.binary })\n        const token = await storage.localFileSystem.createSessionToken(file)\n        let place_event_result\n        await executeAsModal(async () => {\n            const result = await batchPlay(\n                [\n                    {\n                        _obj: 'placeEvent',\n                        ID: 6,\n                        null: {\n                            _path: token,\n                            _kind: 'local',\n                        },\n                        freeTransformCenterState: {\n                            _enum: 'quadCenterState',\n                            _value: 'QCSAverage',\n                        },\n                        offset: {\n                            _obj: 'offset',\n                            horizontal: {\n                                _unit: 'pixelsUnit',\n                                _value: 0,\n                            },\n                            vertical: {\n                                _unit: 'pixelsUnit',\n                                _value: 0,\n                            },\n                        },\n                        _isCommand: true,\n                        _options: {\n                            dialogOptions: 'dontDisplay',\n                        },\n                    },\n                ],\n                {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                }\n            )\n            console.log('placeEmbedd batchPlay result: ', result)\n\n            place_event_result = result[0]\n        })\n\n        return place_event_result\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n// open an image in the plugin folder as new document\n//REFACTOR: move to document.js\nasync function openImageAction() {\n    const storage = require('uxp').storage\n    const fs = storage.localFileSystem\n    try {\n        let pluginFolder = await fs.getPluginFolder()\n        // let theTemplate = await pluginFolder.getEntry(\"/image1.png\");\n        //directory where all image's request folders are. one folder for each request\n        const relative_dir_path = `./server/python_server/`\n\n        const image_path = `${relative_dir_path}/${gCurrentImagePath}`\n        // 'C:/Users/abdul/Desktop/photoshop_plugins/my_plugin_1/server/python_server/output- 1670544300.95411.png'\n        let theTemplate = await pluginFolder.getEntry(image_path)\n\n        await app.open(theTemplate)\n    } catch (e) {\n        console.warn(\"couldn't open image \", e)\n    }\n}\n//REFACTOR: move to psapi.js\nasync function openImageExe() {\n    await require('photoshop').core.executeAsModal(openImageAction)\n}\n// document.getElementById('btnImagesToLayers').addEventListener('click',openImageExe)\n\n// convert a layer to a smart object\nasync function convertToSmartObjectAction() {\n    const batchPlay = require('photoshop').action.batchPlay\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'newPlacedLayer',\n                _isCommand: true,\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {}\n    )\n}\n//REFACTOR: move to psapi.js\nasync function convertToSmartObjectExe() {\n    await require('photoshop').core.executeAsModal(convertToSmartObjectAction)\n}\n\n//REFACTOR: unused, remove?\nasync function silentImagesToLayersExe_old(images_info) {\n    try {\n        g_generation_session.isLoadingActive = true\n\n        await psapi.reSelectMarqueeExe(g_generation_session.selectionInfo)\n        image_path_to_layer = {}\n        console.log(\n            'silentImagesToLayersExe: images_info.images_paths: ',\n            images_info.images_paths\n        )\n        // Returns a Promise that resolves after \"ms\" Milliseconds\n        const timer = (ms) => new Promise((res) => setTimeout(res, ms))\n\n        for (image_info of images_info) {\n            console.log(gCurrentImagePath)\n            //unselect all layers so that the imported layer get place at the top of the document\n            await psapi.unselectActiveLayersExe()\n\n            let placeEventResult\n            // if (base64_images) {\n            //     placeEventResult = await base64ToFile(base64_images) //silent import into the document\n            // } else {\n\n            // }\n            placeEventResult = await base64ToFile(image_info.base64) //silent import into the document\n\n            let layer = await app.activeDocument.layers.filter(\n                (l) => l.id === placeEventResult?.ID\n            )[0]\n            // await openImageExe() //local image to new document\n            // await convertToSmartObjectExe() //convert the current image to smart object\n            let timer_count = 0\n\n            // let layer = await app.activeDocument.activeLayers[0]\n            console.log('loaded layer: ', layer)\n            console.log('placeEventResult?.ID: ', placeEventResult?.ID)\n\n            while (!layer && timer_count <= 10000) {\n                await timer(100) // then the created Promise can be awaited\n                timer_count += 100\n                // layer = await app.activeDocument.activeLayers[0]\n                layer = await app.activeDocument.layers.filter(\n                    (l) => l.id === placeEventResult?.ID\n                )[0]\n                const active_layer = await app.activeDocument.activeLayers[0]\n                console.log('active_layer.id: ', active_layer.id)\n                if (active_layer.id === placeEventResult?.ID) {\n                    layer = active_layer\n                }\n\n                console.log('timer_count: ', timer_count)\n                console.log('loaded layer: ', layer)\n                console.log('placeEventResult?.ID: ', placeEventResult?.ID)\n            }\n\n            if (g_b_use_smart_object === false) {\n                await executeAsModal(async () => {\n                    await layer.rasterize() //rastrize the active layer\n                })\n            }\n\n            await psapi.selectLayersExe([layer])\n            await psapi.layerToSelection(g_generation_session.selectionInfo)\n\n            // await stackLayers() // move the smart object to the original/old document\n            // await psapi.layerToSelection(g_generation_session.selectionInfo) //transform the new smart object layer to fit selection area\n            // layer = await app.activeDocument.activeLayers[0]\n            await g_generation_session.moveToTopOfOutputGroup(layer)\n            // const output_group_id = await g_generation_session.outputGroup.id\n            // let group_index = await psapi.getLayerIndex(output_group_id)\n            // const indexOffset = 1 //1 for background, 0 if no background exist\n            // await executeAsModal(async ()=>{\n            //   await psapi.moveToGroupCommand(group_index - indexOffset, layer.id)\n\n            // })\n\n            image_path_to_layer[image_info.path] = layer\n            // await reselect(selectionInfo)\n        }\n        return image_path_to_layer\n    } catch (e) {\n        console.warn(e)\n    }\n    g_generation_session.isLoadingActive = false\n}\n//REFACTOR: move to psapi.js\nasync function silentImagesToLayersExe(images_info) {\n    //use active layer instead of placeEventResult\n    try {\n        g_generation_session.isLoadingActive = true\n\n        await psapi.reSelectMarqueeExe(g_generation_session.selectionInfo) //why do we reselect the session selection area\n        image_path_to_layer = {}\n        console.log(\n            'silentImagesToLayersExe: images_info.images_paths: ',\n            images_info.images_paths\n        )\n        // Returns a Promise that resolves after \"ms\" Milliseconds\n        // const timer = (ms) => new Promise((res) => setTimeout(res, ms)) //Todo: move this line to it's own utilit function\n\n        for (image_info of images_info) {\n            console.log(gCurrentImagePath)\n            //unselect all layers so that the imported layer get place at the top of the document\n            await psapi.unselectActiveLayersExe()\n\n            let imported_layer\n            // if (base64_images) {\n            //     placeEventResult = await base64ToFile(base64_images) //silent import into the document\n            // } else {\n\n            // }\n            // imported_layer = await base64ToFile(image_info.base64) //silent import into the document\n            const selection_info = await g_generation_session.selectionInfo\n\n            imported_layer = await io.IO.base64ToLayer(\n                image_info.base64,\n                'output_image.png',\n                selection_info.left,\n                selection_info.top,\n                selection_info.width,\n                selection_info.height\n            )\n            if (!layer_util.Layer.doesLayerExist(imported_layer)) {\n                continue //skip if the import vailed\n            }\n            // let layer = await app.activeDocument.layers.filter(\n            //     (l) => l.id === placeEventResult?.ID\n            // )[0]\n\n            let timer_count = 0\n\n            // let layer = await app.activeDocument.activeLayers[0]\n            console.log('imported_layer: ', imported_layer)\n\n            // while (timer_count <= 10000) {\n            //     await timer(100) // then the created Promise can be awaited\n            //     timer_count += 100\n            //     // layer = await app.activeDocument.activeLayers[0]\n\n            //     console.log('timer_count: ', timer_count)\n            //     console.log('loaded layer: ', imported_layer)\n            // }\n\n            if (g_b_use_smart_object === false) {\n                await executeAsModal(async () => {\n                    await imported_layer.rasterize() //rastrize the active layer\n                })\n            }\n\n            // await psapi.selectLayersExe([imported_layer])\n            // await psapi.layerToSelection(g_generation_session.selectionInfo)// not needed\n\n            await g_generation_session.moveToTopOfOutputGroup(imported_layer)\n            await psapi.setVisibleExe(imported_layer, false) // turn off the visibility for the layer\n            image_path_to_layer[image_info.path] = imported_layer\n            // await reselect(selectionInfo)\n        }\n        return image_path_to_layer\n    } catch (e) {\n        console.warn(e)\n    }\n    g_generation_session.isLoadingActive = false\n}\n\n//stack layer to original document\n//REFACTOR: move to psapi.js\nasync function stackLayers() {\n    //workingDoc is the project you are using stable diffusion in\n    const workingDoc = app.documents[0]\n    //you should not open two multiple projects this script assume there is only one project opened\n    const docsToStack = app.documents.filter(\n        (doc) => doc._id !== workingDoc._id\n    )\n    let docCounter = 0\n\n    // execute as modal is required for functions that change the state of Photoshop or documents\n    // think of it as a function that 'wraps' yours and tells Photoshop to go into a modal state and not allow anything to interrupt it from doing whatever is contained in the executeAsModal\n    // we also call it with the await keyword to tell JS that we want to wait for it to complete before moving on to later code (in this case there isn't any though)\n    await require('photoshop').core.executeAsModal(async () => {\n        // increment counter\n        docCounter++\n\n        // loop through other open docs\n        for (const doc of docsToStack) {\n            // flatten\n            // doc.flatten();\n\n            // rename layer with counter\n            doc.layers[0].name = `Layer ${docCounter}`\n\n            // increment counter\n            docCounter++\n\n            // duplicate layer to docZero\n            doc.layers[0].duplicate(workingDoc)\n\n            // close doc\n            await doc.closeWithoutSaving()\n        }\n    })\n}\n\nfunction removeInitImageFromViewer() {}\nfunction removeMaskFromViewer() {}\n//REFACTOR: move to viewer.js\nasync function viewerThumbnailclickHandler(e, viewer_obj_owner) {\n    if (g_isViewerMenuDisabled) {\n        return g_isViewerMenuDisabled\n    }\n\n    let click_type = Enum.clickTypeEnum['Click']\n\n    if (e.shiftKey) {\n        click_type = Enum.clickTypeEnum['ShiftClick']\n    } else if (e.altKey) {\n        click_type = Enum.clickTypeEnum['AltClick']\n    }\n\n    if (\n        viewer_obj_owner.isActive() &&\n        click_type === Enum.clickTypeEnum['Click']\n    ) {\n        //convert consecutive clicks to AltClick\n        click_type = Enum.clickTypeEnum['SecondClick']\n        console.log('converted click_type: ', click_type)\n    }\n\n    await executeAsModal(async () => {\n        //get type of click\n\n        await viewer_obj_owner.click(click_type)\n    })\n}\n// async function NewViewerImageClickHandler(img, viewer_obj_owner) {\n//     try {\n\n//     } catch (e) {\n//         console.warn(e)\n//     }\n// }\n//REFACTOR: move to viewer.js\nfunction createViewerImgHtml(output_dir_relative, image_path, base64_image) {\n    const img = document.createElement('img')\n    // img.src = `${output_dir_relative}/${image_path}`\n    img.src = base64ToSrc(base64_image)\n    img.className = 'viewer-image'\n    console.log('image_path: ', image_path)\n    // img.dataset.image_id = layer_id\n    // img.dataset.image_path = image_path // image_path is not the same as src\n    return img\n}\n\n//REFACTOR: move to psapi.js\nfunction toggleLayerVisibility(layer, b_on) {\n    try {\n        layer.visible = b_on\n    } catch (e) {\n        console.warn(e)\n    }\n}\n//REFACTOR: move to psapi.js\nasync function turnMaskVisible(\n    b_mask_group_on,\n    b_white_mask_on,\n    b_solid_black_mask_on\n) {\n    //will turn a mask group, white layer mask, and the solid black layer on and off\n    try {\n        await executeAsModal(() => {\n            toggleLayerVisibility(g_mask_group, b_mask_group_on)\n            toggleLayerVisibility(g_white_mask, b_white_mask_on)\n            toggleLayerVisibility(g_solid_black_mask, b_solid_black_mask_on)\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//REFACTOR: move to events.js\ndocument\n    .getElementById('btnLoadPromptShortcut')\n    .addEventListener('click', async function () {\n        await sd_tab_util.loadPromptShortcut()\n    })\n//REFACTOR: move to events.js\ndocument\n    .getElementById('btnUpdatePromptShortcut')\n    .addEventListener('click', async function () {\n        try {\n            // prompt_shortcut = await sdapi.loadPromptShortcut()\n            const prompt_shortcut_string =\n                document.getElementById('taPromptShortcut').value\n            const prompt_shortcut = JSON.parse(prompt_shortcut_string)\n            var newKey = document.getElementById('KeyPromptShortcut').value\n            var newValue = document.getElementById('ValuePromptShortcut').value\n            console.log(newKey)\n            console.log(newValue)\n            prompt_shortcut[newKey] = newValue\n            var JSONInPrettyFormat = JSON.stringify(\n                prompt_shortcut,\n                undefined,\n                4\n            )\n            console.log(JSONInPrettyFormat)\n            document.getElementById('taPromptShortcut').value =\n                JSONInPrettyFormat\n            await refreshPromptMenu()\n        } catch (e) {\n            console.warn(`loadPromptShortcut warning: ${e}`)\n        }\n    })\n//REFACTOR: move to events.js\ndocument\n    .getElementById('btnSavePromptShortcut')\n    .addEventListener('click', async function () {\n        try {\n            const r1 = await dialog_box.prompt(\n                'Are you sure you want to save prompt shortcut?',\n                \"This will override your old prompt shortcut file, you can't undo this operation\",\n                ['Cancel', 'Save']\n            )\n            if ((r1 || 'Save') !== 'Save') {\n                /* cancelled or No */\n                console.log('cancel')\n            } else {\n                /* Yes */\n                console.log('Save')\n\n                prompt_shortcut_string =\n                    document.getElementById('taPromptShortcut').value\n                let prompt_shortcut = JSON.parse(prompt_shortcut_string)\n\n                prompt_shortcut = await sdapi.savePromptShortcut(\n                    prompt_shortcut\n                )\n                // var JSONInPrettyFormat = JSON.stringify(prompt_shortcut, undefined, 4);\n                console.log('prompt_shortcut was saved: ', prompt_shortcut)\n            }\n        } catch (e) {\n            console.warn(`savePromptShortcut warning: ${e}`)\n        }\n    })\n\n//REFACTOR: move to document.js\nasync function loadPromptShortcut() {\n    let prompt_shortcut = await sdapi.loadPromptShortcut() // always return json object or empty object {}\n    if (!Object.keys(prompt_shortcut).length) {\n        //load the default prompt shortcut if we have an empty prompt shortcut object (on failure to load from file)\n        prompt_shortcut = promptShortcutExample()\n    }\n    html_manip.setPromptShortcut(prompt_shortcut) // fill the prompt shortcut textarea\n    await refreshPromptMenu() //refresh the prompt menu\n}\n//REFACTOR: move to ui.js\nasync function refreshPromptMenu() {\n    try {\n        //get the prompt_shortcut_json\n        //iterate over the each entery\n        const prompt_shortcut = html_manip.getPromptShortcut()\n        const prompt_shortcut_menu = document.getElementById(\n            'mPromptShortcutMenu'\n        )\n        prompt_shortcut_menu.innerHTML = ''\n\n        for (const [key, value] of Object.entries(prompt_shortcut)) {\n            if (value.trim() === '') {\n                //skip empty spaces\n                continue\n            }\n            const menu_item_element = document.createElement('sp-menu-item')\n\n            menu_item_element.innerHTML = key\n            prompt_shortcut_menu.appendChild(menu_item_element)\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n//REFACTOR: move to events.js\ndocument\n    .getElementById('mPromptShortcutMenu')\n    .addEventListener('change', (evt) => {\n        const prompt_shortcut = html_manip.getPromptShortcut()\n        const key = evt.target.value\n        console.log('key:', key)\n        changePromptShortcutKey(key)\n        changePromptShortcutValue(prompt_shortcut[key])\n    })\n//REFACTOR: move to events.js\ndocument\n    .getElementById('btnRefreshPromptShortcutMenu')\n    .addEventListener('click', async () => {\n        await refreshPromptMenu()\n    })\n//REFACTOR: move to ui.js\nfunction changePromptShortcutKey(new_key) {\n    document.getElementById('KeyPromptShortcut').value = new_key\n}\n//REFACTOR: move to ui.js\nfunction changePromptShortcutValue(new_value) {\n    document.getElementById('ValuePromptShortcut').value = new_value\n}\n\n//REFACTOR: move to document.js\nasync function downloadIt(link, writeable_entry, image_file_name) {\n    const image = await fetch(link)\n    console.log(link)\n    const storage = require('uxp').storage\n    const fs = storage.localFileSystem\n\n    try {\n        const img = await image.arrayBuffer()\n        // const file = await fs.getFileForSaving(\"image.png\");\n        // const folder = await storage.localFileSystem.getTemporaryFolder()\n        const file = await writeable_entry.createFile(image_file_name, {\n            overwrite: true,\n        })\n        // const file = await fs.getTempFolder()\n\n        await file.write(img)\n        const currentDocument = app.activeDocument\n        let newDocument\n        let new_layer\n        try {\n            newDocument = await app.open(file)\n            if (currentDocument) {\n                new_layer = await newDocument.activeLayers[0].duplicate(\n                    currentDocument\n                )\n                await newDocument.closeWithoutSaving()\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n\n        if (!file) {\n            return\n        }\n        return new_layer\n    } catch (e) {\n        console.warn(e)\n    }\n}\n//REFACTOR: move to document.js\nasync function downloadItExe(link, writeable_entry, image_file_name) {\n    let new_layer\n    await executeAsModal(async () => {\n        try {\n            new_layer = await downloadIt(link, writeable_entry, image_file_name)\n        } catch (e) {\n            console.warn(e)\n        }\n    })\n    return new_layer\n}\n\n//REFACTOR: move to psapi.js\nfunction base64ToSrc(base64_image) {\n    const image_src = `data:image/png;base64, ${base64_image}`\n    return image_src\n}\n\nconst py_re = require('./utility/sdapi/python_replacement')\n\nfunction getDimensions(image) {\n    return new Promise((resolve, reject) => {\n        var img = new Image()\n        img.src = image\n\n        img.addEventListener('load', function () {\n            // image.width × image.height\n            console.log('image loaded:', img.width, img.height)\n            resolve({ width: img.width, height: img.height })\n        })\n\n        // img.onload = () => {\n\n        //     resolve({ width: img.width, height: img.height })\n        // }\n    })\n}\n\n//REFACTOR: move to events.js\n\nfunction switchMenu(rb) {\n    const tab_button_name = rb.dataset['tab-name']\n    const tab_page_name = `${tab_button_name}-page`\n\n    try {\n        const contianer_class = rb.parentElement.dataset['container-class']\n        const radio_group = rb.parentElement\n        document\n            .getElementById(tab_button_name)\n            .addEventListener('click', () => {\n                document.getElementById(tab_button_name)\n                const option_container = document\n                    .getElementById(tab_page_name)\n                    .querySelector(`.${contianer_class}`)\n                // .querySelector('.subTabOptionsContainer')\n\n                rb.checked = true\n                option_container.appendChild(radio_group)\n            })\n\n        rb.onclick = () => {\n            document.getElementById(tab_button_name).click()\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//REFACTOR: move to events.js\ndocument\n    .getElementById('btnSaveHordeSettings')\n    .addEventListener('click', async () => {\n        await horde_native.HordeSettings.saveSettings()\n    })\n\ndocument\n    .getElementById('btnSaveHordeSettings')\n    .addEventListener('click', async () => {\n        await horde_native.HordeSettings.saveSettings()\n    })\n\nlet g_viewer_sub_menu_list = []\n\nconst submenu = {\n    viewer: {\n        value: 'viewer',\n        Label: 'Viewer',\n        'data-tab-name': 'sp-viewer-tab',\n    },\n    prompts_library: {\n        value: 'prompts-library',\n        Label: 'Prompts Library',\n        'data-tab-name': 'sp-prompts-library-tab',\n    },\n\n    image_search: {\n        value: 'image_search',\n        Label: 'Image Search',\n        'data-tab-name': 'sp-image_search-tab',\n    },\n}\n\n{\n    /* <li>\n                                <input\n                                    type=\"radio\"\n                                    id=\"option1\"\n                                    name=\"options\"\n                                    checked\n                                    class=\"sub-menu-tab-class\"\n                                />\n                                <label for=\"option1\">Option 1</label>\n                            </li> */\n}\n\nconst viewer_sub_menu_html = document.getElementById('viewer-sub-menu')\n// const li_elm = document.createElement('li')\n// const input_option = document.createElement('input')\n// const label_option = document.createElement('label')\n\n// li_elm.appendChild(input_option)\n// li_elm.appendChild(label_option)\n// viewer_sub_menu_html.appendChild(li_elm)\n\nfor (const [option_id, option_data] of Object.entries(submenu)) {\n    const li = document.createElement('li')\n\n    li.innerHTML = `\n    <input\n        type=\"radio\"\n        id=\"${option_id}\"\n        name=\"options\"\n        checked\n        class=\"sub-menu-tab-class\"\n        data-tab-name='${option_data['data-tab-name']}'\n        \n    />\n    <label for=\"${option_id}\">${option_data.Label}</label>\n`\n\n    viewer_sub_menu_html.appendChild(li)\n}\n\nfunction switchMenu_new(rb) {\n    const tab_button_name = rb.dataset['tab-name']\n    const tab_page_name = `${tab_button_name}-page`\n\n    try {\n        const contianer_class =\n            rb.parentElement.parentElement.parentElement.dataset[\n                'container-class'\n            ] //input_option.li.ul.div.dataset['container-class']\n        const radio_group = rb.parentElement.parentElement.parentElement //radio_group in this case is ul\n        document\n            .getElementById(tab_button_name)\n            .addEventListener('click', () => {\n                document.getElementById(tab_button_name)\n                const option_container = document\n                    .getElementById(tab_page_name)\n                    .querySelector(`.${contianer_class}`)\n                // .querySelector('.subTabOptionsContainer')\n\n                rb.checked = true\n                option_container.appendChild(radio_group)\n            })\n\n        rb.parentElement.onclick = () => {\n            document.getElementById(tab_button_name).click()\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\ndocument.getElementsByClassName('sub-menu-tab-class').forEach((element) => {\n    switchMenu_new(element)\n\n    // const li_element = element.parentElement\n    // li_element.addEventListener('click', (event) => {\n    //     //doesn't get trigger don't know why\n    //     console.log('sub menu clicked')\n    //     element.checked = true\n    // })\n    // switchMenu_new(element)\n})\nArray.from(document.querySelectorAll('.rbSubTab')).forEach((rb) => {\n    switchMenu(rb)\n})\n\n// document.getElementById('scrollToViewer').addEventListener('click', () => {\n\n//     document\n//         .querySelector('#sp-stable-diffusion-ui-tab-page .reactViewerContainer')\n//         .scrollIntoView()\n// })\n\nconst photoshop = require('photoshop')\nconst uxp = require('uxp')\nasync function openFileFromUrl(url, format = 'gif') {\n    try {\n        // Download the image\n        const response = await fetch(url)\n        // const blob = await response.blob()\n\n        // Convert the blob to an ArrayBuffer\n        const arrayBuffer = await response.arrayBuffer()\n\n        // Save the image to a temporary file\n        const tempFolder = await storage.localFileSystem.getTemporaryFolder()\n        const randomNumber = Math.floor(Math.random() * 1000000000) // generates a random number between 0 and 999999999\n        const tempFile = await tempFolder.createFile(\n            `temp_${randomNumber}.${format}`,\n            {\n                overwrite: true,\n            }\n        )\n        await tempFile.write(arrayBuffer)\n\n        // Open the file in Photoshop\n        const document = await app.open(tempFile)\n        console.log(`Opened document: ${document.title}`)\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nasync function openFileFromUrlExe(url, format = 'gif') {\n    await executeAsModal(async () => {\n        await openFileFromUrl(url, format)\n    })\n}\n"
  },
  {
    "path": "install.py",
    "content": "import os\nfrom pathlib import Path\nfrom launch import git, run\nimport launch\nimport sys\n\n# launch.run(f'git pull', f\"updating auto-photoshop plugin\",\n#         f\"Couldn't update auto-photoshop plugin\")\n\n\nREPO_LOCATION = Path(__file__).parent\n# auto_update = os.environ.get(\"AUTO_UPDATE\", \"True\").lower() in {\"true\", \"yes\"}\nauto_update = True\nextension_branch = \"master\"\n# extension_branch = \"horde_native\"\n# extension_branch = \"auto_extension_ccx_1_1_7\"\n\nif auto_update:\n    print(\"[Auto-Photoshop-SD] Attempting auto-update...\")\n\n    try:\n        checkout_result = run(\n            f'\"{git}\" -C \"{REPO_LOCATION}\" checkout {extension_branch}',\n            \"[Auto-Photoshop-SD] switch branch to extension branch.\",\n        )\n        print(\"checkout_result:\", checkout_result)\n\n        branch_result = run(\n            f'\"{git}\" -C \"{REPO_LOCATION}\" branch',\n            \"[Auto-Photoshop-SD] Current Branch.\",\n        )\n        print(\"branch_result:\", branch_result)\n\n        fetch_result = run(\n            f'\"{git}\" -C \"{REPO_LOCATION}\" fetch', \"[Auto-Photoshop-SD] Fetch upstream.\"\n        )\n        print(\"fetch_result:\", fetch_result)\n\n        pull_result = run(\n            f'\"{git}\" -C \"{REPO_LOCATION}\" pull', \"[Auto-Photoshop-SD] Pull upstream.\"\n        )\n        print(\"pull_result:\", pull_result)\n\n    except Exception as e:\n        print(\"[Auto-Photoshop-SD] Auto-update failed:\")\n        print(e)\n        print(\"[Auto-Photoshop-SD] Ensure git was used to install extension.\")\n\n\n# print(\"Auto-Photoshop-SD plugin is installing\")\nimport pkg_resources\n\n\ndef install_or_update_package(package_name, package_version):\n    if not launch.is_installed(package_name):\n        launch.run_pip(\n            f\"install {package_name}=={package_version}\",\n            \"requirements for Auto-Photoshop Image Search\",\n        )\n    else:  # it's installed but we need to check for update\n        version = pkg_resources.get_distribution(package_name).version\n        if version != package_version:\n            print(\n                f\"{package_name} version: {version} will update to version: {package_version}\"\n            )\n            launch.run_pip(\n                f\"install {package_name}=={package_version}\",\n                \"update requirements for Auto-Photoshop Image Search\",\n            )\n\n\n# Now we can use this function to install or update the packages\ninstall_or_update_package(\"duckduckgo_search\", \"3.9.9\")\ninstall_or_update_package(\"httpx\", \"0.24.1\")\n"
  },
  {
    "path": "manifest.json",
    "content": "{\n    \"id\": \"auto.photoshop.stable.diffusion.plugin\",\n    \"name\": \"Auto Photoshop Stable Diffusion Plugin\",\n    \"version\": \"1.4.1\",\n    \"host\": {\n        \"app\": \"PS\",\n        \"minVersion\": \"24.0.0\"\n    },\n    \"main\": \"index.html\",\n    \"manifestVersion\": 5,\n    \"requiredPermissions\": {\n        \"allowCodeGenerationFromStrings\": true,\n        \"network\": {\n            \"domains\": \"all\"\n        },\n        \"launchProcess\": {\n            \"schemes\": [\n                \"http\",\n                \"https\",\n                \"mailto\"\n            ],\n            \"extensions\": [\n                \".png\",\n                \".jpg\",\n                \".pdf\",\n                \"\"\n            ]\n        },\n        \"clipboard\": \"readAndWrite\",\n        \"localFileSystem\": \"request\",\n        \"ipc\": {\n            \"enablePluginCommunication\": true\n        }\n    },\n    \"entrypoints\": [\n        {\n            \"type\": \"panel\",\n            \"id\": \"main_panel\",\n            \"label\": {\n                \"default\": \"Auto-Photoshop-SD\",\n                \"en-US\": \"Auto-Photoshop-SD\",\n                \"es-ES\": \"Auto-Photoshop-SD\",\n                \"zh-CN\": \"SD插件（明空汉化）\"\n            },\n            \"minimumSize\": {\n                \"width\": 400,\n                \"height\": 400\n            },\n            \"maximumSize\": {\n                \"width\": 1200,\n                \"height\": 10000\n            },\n            \"preferredDockedSize\": {\n                \"width\": 150,\n                \"height\": 800\n            },\n            \"preferredFloatingSize\": {\n                \"width\": 300,\n                \"height\": 800\n            },\n            \"commands\": [\n                {\n                    \"id\": \"show_alert\",\n                    \"label\": {\n                        \"default\": \"Show Alert\",\n                        \"en-US\": \"Show Alert (US)\",\n                        \"es-ES\": \"Show Alert (ES)\"\n                    }\n                }\n            ],\n            \"icons\": [\n                {\n                    \"width\": 23,\n                    \"height\": 23,\n                    \"path\": \"icon/panel.png\",\n                    \"scale\": [\n                        1,\n                        2\n                    ],\n                    \"theme\": [\n                        \"all\"\n                    ],\n                    \"species\": [\n                        \"chrome\"\n                    ]\n                }\n            ]\n        },\n        {\n            \"type\": \"panel\",\n            \"id\": \"second_panel\",\n            \"label\": {\n                \"default\": \"Second Auto-Photoshop-SD\",\n                \"en-US\": \"Second Auto-Photoshop-SD\",\n                \"es-ES\": \"Second Auto-Photoshop-SD\",\n                \"zh-CN\": \"SD插件（明空汉化）\"\n            },\n            \"minimumSize\": {\n                \"width\": 100,\n                \"height\": 100\n            },\n            \"maximumSize\": {\n                \"width\": 1200,\n                \"height\": 10000\n            },\n            \"preferredDockedSize\": {\n                \"width\": 150,\n                \"height\": 800\n            },\n            \"preferredFloatingSize\": {\n                \"width\": 300,\n                \"height\": 800\n            },\n            \"commands\": [\n                {\n                    \"id\": \"show_alert\",\n                    \"label\": {\n                        \"default\": \"Show Alert\",\n                        \"en-US\": \"Show Alert (US)\",\n                        \"es-ES\": \"Show Alert (ES)\"\n                    }\n                }\n            ],\n            \"icons\": [\n                {\n                    \"width\": 23,\n                    \"height\": 23,\n                    \"path\": \"icon/panel.png\",\n                    \"scale\": [\n                        1,\n                        2\n                    ],\n                    \"theme\": [\n                        \"all\"\n                    ],\n                    \"species\": [\n                        \"chrome\"\n                    ]\n                }\n            ]\n        },\n        {\n            \"type\": \"panel\",\n            \"id\": \"toolbar\",\n            \"label\": {\n                \"default\": \"toolbar Auto-Photoshop-SD\",\n                \"en-US\": \"toolbar Auto-Photoshop-SD\",\n                \"es-ES\": \"toolbar Auto-Photoshop-SD\"\n            },\n            \"minimumSize\": {\n                \"width\": 30,\n                \"height\": 100\n            },\n            \"maximumSize\": {\n                \"width\": 1200,\n                \"height\": 10000\n            },\n            \"preferredDockedSize\": {\n                \"width\": 30,\n                \"height\": 800\n            },\n            \"preferredFloatingSize\": {\n                \"width\": 30,\n                \"height\": 800\n            },\n            \"commands\": [\n                {\n                    \"id\": \"show_alert\",\n                    \"label\": {\n                        \"default\": \"Show Alert\",\n                        \"en-US\": \"Show Alert (US)\",\n                        \"es-ES\": \"Show Alert (ES)\"\n                    }\n                }\n            ],\n            \"icons\": [\n                {\n                    \"width\": 23,\n                    \"height\": 23,\n                    \"path\": \"icon/panel.png\",\n                    \"scale\": [\n                        1,\n                        2\n                    ],\n                    \"theme\": [\n                        \"all\"\n                    ],\n                    \"species\": [\n                        \"chrome\"\n                    ]\n                }\n            ]\n        }\n    ],\n    \"icons\": [\n        {\n            \"width\": 48,\n            \"height\": 48,\n            \"path\": \"icon/plugin.png\",\n            \"scale\": [\n                1,\n                2\n            ],\n            \"theme\": [\n                \"all\"\n            ],\n            \"species\": [\n                \"pluginList\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"auto-photoshop-stable-diffusion-plugin\",\n    \"version\": \"1.3.3\",\n    \"description\": \"A user-friendly plug-in that makes it easy to generate stable diffusion images inside Photoshop using Automatic1111-sd-webui as a backend.\",\n    \"author\": \"Adobe Inc\",\n    \"license\": \"Apache-2.0\",\n    \"dependencies\": {\n        \"@types/photoshop\": \"^24.5.1\",\n        \"@types/react\": \"^18.2.6\",\n        \"@types/react-dom\": \"^18.2.4\",\n        \"changedpi\": \"^1.0.4\",\n        \"fastify\": \"^4.10.2\",\n        \"jimp\": \"^0.16.2\",\n        \"madge\": \"^6.0.0\",\n        \"md5\": \"^2.3.0\",\n        \"mobx\": \"^6.9.0\",\n        \"mobx-react\": \"^7.6.0\",\n        \"react\": \"^18.2.0\",\n        \"react-dom\": \"^18.2.0\",\n        \"util\": \"^0.12.5\"\n    },\n    \"main\": \"index.js\",\n    \"directories\": {\n        \"test\": \"test\"\n    },\n    \"devDependencies\": {\n        \"@babel/core\": \"^7.21.8\",\n        \"@babel/plugin-proposal-object-rest-spread\": \"^7.20.7\",\n        \"@babel/plugin-syntax-class-properties\": \"^7.12.13\",\n        \"@babel/plugin-transform-react-jsx\": \"^7.21.5\",\n        \"@svgr/webpack\": \"^8.0.1\",\n        \"babel-loader\": \"^9.1.2\",\n        \"chalk\": \"^5.3.0\",\n        \"clean-webpack-plugin\": \"^4.0.0\",\n        \"commander\": \"^11.0.0\",\n        \"copy-webpack-plugin\": \"^11.0.0\",\n        \"css-loader\": \"^6.7.3\",\n        \"file-loader\": \"^6.2.0\",\n        \"glob\": \"^10.3.4\",\n        \"nodemon\": \"^2.0.22\",\n        \"prettier\": \"2.8.3\",\n        \"style-loader\": \"^3.3.2\",\n        \"terser-webpack-plugin\": \"^3.0.8\",\n        \"ts-loader\": \"^9.4.2\",\n        \"typescript\": \"^5.0.4\",\n        \"url-loader\": \"^4.1.1\",\n        \"webpack\": \"^5.82.1\",\n        \"webpack-cli\": \"^5.1.1\",\n        \"yazl\": \"^2.5.1\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n        \"watch\": \"npx webpack --config ./build-script/webpack.config.js --watch --devtool eval-source-map\",\n        \"build\": \"npx webpack --config ./build-script/webpack.config.js\",\n        \"publish\": \"npx webpack --config ./build-script/webpack.config.js --mode production\",\n        \"format\": \"npx prettier -w typescripts\"\n    },\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"git+https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin.git\"\n    },\n    \"keywords\": [],\n    \"bugs\": {\n        \"url\": \"https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/issues\"\n    },\n    \"homepage\": \"https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin#readme\"\n}\n"
  },
  {
    "path": "presets/ctrlnet_inpaint.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"inpaint\",\n        \"rb_mode\": \"inpaint\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"ratio\": 1,\n        \"cfg\": 7,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 1,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"image_cfg_scale\": 1.5,\n        \"mask_blur\": 0,\n        \"mask_expansion\": 0,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 2,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": [\n        {\n            \"enabled\": true,\n            \"module\": \"inpaint_global_harmonious\",\n            \"model\": \"control_v11p_sd15_inpaint [ebff9138]\",\n            \"weight\": 1,\n            \"resize_mode\": \"Scale to Fit (Inner Fit)\",\n            \"lowvram\": true,\n            \"processor_res\": 512,\n            \"threshold_a\": 0,\n            \"threshold_b\": 0,\n            \"guidance_start\": 0,\n            \"guidance_end\": 1,\n            \"guessmode\": false,\n            \"control_mode\": \"ControlNet is more important\",\n            \"pixel_perfect\": true,\n            \"auto_image\": true,\n            \"filter_keyword\": \"Inpaint\"\n        },\n        {},\n        {},\n        {},\n        {},\n        {},\n        {}\n    ]\n}"
  },
  {
    "path": "presets/ctrlnet_inpaint_tile.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"inpaint\",\n        \"rb_mode\": \"inpaint\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"ratio\": 1,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 1,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"image_cfg_scale\": 1.5,\n        \"mask_blur\": 0,\n        \"mask_expansion\": 0,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 2,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": [\n        {\n            \"enabled\": true,\n            \"module\": \"inpaint_global_harmonious\",\n            \"model\": \"control_v11p_sd15_inpaint [ebff9138]\",\n            \"weight\": 1,\n            \"resize_mode\": \"Scale to Fit (Inner Fit)\",\n            \"lowvram\": true,\n            \"processor_res\": 512,\n            \"threshold_a\": 0,\n            \"threshold_b\": 0,\n            \"guidance_start\": 0,\n            \"guidance_end\": 1,\n            \"guessmode\": false,\n            \"control_mode\": \"ControlNet is more important\",\n            \"pixel_perfect\": true,\n            \"auto_image\": true,\n            \"filter_keyword\": \"Inpaint\"\n        },\n        {\n            \"enabled\": true,\n            \"module\": \"tile_resample\",\n            \"model\": \"control_v11f1e_sd15_tile [a371b31b]\",\n            \"weight\": 0.4,\n            \"resize_mode\": \"Scale to Fit (Inner Fit)\",\n            \"lowvram\": true,\n            \"processor_res\": 512,\n            \"threshold_a\": 1,\n            \"threshold_b\": 0,\n            \"guidance_start\": 0,\n            \"guidance_end\": 1,\n            \"guessmode\": false,\n            \"control_mode\": \"Balanced\",\n            \"pixel_perfect\": true,\n            \"auto_image\": true,\n            \"filter_keyword\": \"Tile\"\n        },\n        {},\n        {},\n        {},\n        {},\n        {}\n    ]\n}"
  },
  {
    "path": "presets/ctrlnet_outpaint.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"outpaint\",\n        \"rb_mode\": \"outpaint\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"ratio\": 1,\n        \"cfg\": 7,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 1,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"image_cfg_scale\": 1.5,\n        \"mask_blur\": 0,\n        \"mask_expansion\": 10,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 3,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": [\n        {\n            \"enabled\": true,\n            \"module\": \"inpaint_global_harmonious\",\n            \"model\": \"control_v11p_sd15_inpaint [ebff9138]\",\n            \"weight\": 1,\n            \"resize_mode\": \"Scale to Fit (Inner Fit)\",\n            \"lowvram\": true,\n            \"processor_res\": 512,\n            \"threshold_a\": 0,\n            \"threshold_b\": 0,\n            \"guidance_start\": 0,\n            \"guidance_end\": 1,\n            \"guessmode\": false,\n            \"control_mode\": \"ControlNet is more important\",\n            \"pixel_perfect\": true,\n            \"auto_image\": true,\n            \"filter_keyword\": \"Inpaint\"\n        },\n        {},\n        {},\n        {},\n        {},\n        {},\n        {}\n    ]\n}"
  },
  {
    "path": "presets/default.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"txt2img\",\n        \"rb_mode\": \"txt2img\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"steps\": 20,\n        \"width\": 512,\n        \"height\": 512,\n        \"ratio\": 1,\n        \"cfg\": 7,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 0.7,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"sampler_name\": \"Euler a\",\n        \"image_cfg_scale\": 1.5,\n        \"seed\": \"-1\",\n        \"mask_blur\": 0,\n        \"mask_expansion\": 0,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 0,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": [\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {}\n    ]\n}"
  },
  {
    "path": "presets/img2img.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"img2img\",\n        \"rb_mode\": \"img2img\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"steps\": 20,\n\n        \"ratio\": 1,\n        \"cfg\": 7,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 0.6,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"image_cfg_scale\": 1.5,\n        \"mask_blur\": 0,\n        \"mask_expansion\": 10,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 2,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": [{}, {}, {}, {}, {}, {}, {}]\n}\n"
  },
  {
    "path": "presets/inpaint.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"inpaint\",\n        \"rb_mode\": \"inpaint\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"steps\": 20,\n        \"ratio\": 1,\n        \"cfg\": 7,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 0.7,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"image_cfg_scale\": 1.5,\n        \"mask_blur\": 0,\n        \"mask_expansion\": 0,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 1,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": [{}, {}, {}, {}, {}, {}, {}]\n}\n"
  },
  {
    "path": "presets/outpaint.json",
    "content": "{\n    \"sd_tab_preset\": {\n        \"is_lasso_mode\": false,\n        \"mode\": \"outpaint\",\n        \"rb_mode\": \"outpaint\",\n        \"batch_size\": 1,\n        \"batch_count\": 1,\n        \"steps\": 20,\n        \"ratio\": 1,\n        \"cfg\": 7,\n        \"b_width_height_link\": true,\n        \"denoising_strength\": 0.92,\n        \"hr_denoising_strength\": 0.7,\n        \"inpaint_full_res\": false,\n        \"enable_hr\": false,\n        \"image_cfg_scale\": 1.5,\n        \"mask_blur\": 0,\n        \"mask_expansion\": 10,\n        \"inpaint_full_res_padding\": 0,\n        \"hr_scale\": 2,\n        \"hr_resize_x\": 512,\n        \"hr_resize_y\": 512,\n        \"hr_second_pass_steps\": 0,\n        \"restore_faces\": false,\n        \"inpainting_fill\": 2,\n        \"hr_upscaler\": \"\",\n        \"selection_mode\": \"ratio\"\n    },\n    \"controlnet_tab_preset\": []\n}"
  },
  {
    "path": "psapi.js",
    "content": "const app = window.require('photoshop').app\nconst batchPlay = require('photoshop').action.batchPlay\nconst { executeAsModal } = require('photoshop').core\nconst constants = require('photoshop').constants\n// console.log(constants.ResampleMethod.BILINEAR)\n// const export_png = require('./export_png')\n\n// const { layerToSelection } = require('./helper')\n\nconst storage = require('uxp').storage\nconst fs = storage.localFileSystem\n\nasync function createSolidLayer(r, g, b) {\n    console.warn('this function is deprecated')\n    await executeAsModal(async () => {\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'make',\n                    _target: [\n                        {\n                            _ref: 'contentLayer',\n                        },\n                    ],\n                    using: {\n                        _obj: 'contentLayer',\n                        type: {\n                            _obj: 'solidColorLayer',\n                            color: {\n                                _obj: 'RGBColor',\n                                red: r,\n                                grain: g,\n                                blue: b,\n                            },\n                        },\n                    },\n                    _options: {\n                        dialogOptions: 'dontDisplay',\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n    })\n}\n\nasync function makeGroupCommand() {\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'make',\n                _target: [\n                    {\n                        _ref: 'layerSection',\n                    },\n                ],\n                layerSectionStart: 405,\n                layerSectionEnd: 406,\n                name: 'Group 16',\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n\n    console.log('makeGroupCommand: ', result)\n\n    return result\n}\nasync function createEmptyGroup(name = 'New Group') {\n    let groupLayer\n    await executeAsModal(async () => {\n        await makeGroupCommand()\n        groupLayer = app.activeDocument.activeLayers[0]\n        groupLayer.name = name\n    })\n    console.log('groupLayer:', groupLayer)\n    return groupLayer\n}\n\nasync function moveToGroupCommand(to_index, layerIDs) {\n    const batchPlay = require('photoshop').action.batchPlay\n    console.log('to_index:', to_index)\n    console.log('layerIDs:', layerIDs)\n\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'move',\n                _target: [\n                    {\n                        _ref: 'layer',\n                        _enum: 'ordinal',\n                        _value: 'targetEnum',\n                    },\n                ],\n                to: {\n                    _ref: 'layer',\n                    _index: to_index,\n                },\n                adjustment: false,\n                version: 5,\n                layerID: layerIDs,\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n}\nfunction MoveToGroupExe(toIndex, layerIDs) {\n    try {\n        executeAsModal(async () => {\n            await moveToGroupCommand(toIndex, layerIDs)\n        })\n    } catch (e) {\n        console.warn('executeCommand error:', e)\n    }\n}\n\nasync function getIndexCommand(layer_id) {\n    const idx = batchPlay(\n        [\n            {\n                _obj: 'get',\n                _target: [\n                    {\n                        _property: 'itemIndex',\n                    },\n                    {\n                        _ref: 'layer',\n                        // _name: 'myGroup'\n                        _id: layer_id,\n                    },\n                ],\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        { synchronousExecution: true }\n    )[0]['itemIndex']\n    console.log('index:', idx)\n    return idx\n}\n\nasync function getLayerIndex(layer_id) {\n    const { executeAsModal } = require('photoshop').core\n    try {\n        let index\n        await executeAsModal(async () => {\n            index = await getIndexCommand(layer_id)\n            console.log('getIndex: ', index)\n        })\n        return index\n    } catch (e) {\n        console.warn('getIndex error:', e)\n    }\n}\n\nasync function unselectActiveLayers() {\n    const layers = await app.activeDocument.activeLayers\n    for (layer of layers) {\n        layer.selected = false\n    }\n}\nasync function unselectActiveLayersExe() {\n    await executeAsModal(async () => {\n        await unselectActiveLayers()\n    })\n}\nasync function selectLayers(layers) {\n    await unselectActiveLayers()\n    for (layer of layers) {\n        try {\n            if (layer) {\n                const is_visible = layer.visible // don't change the visibility when selecting the layer\n                layer.selected = true\n                layer.visible = is_visible\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\n\nasync function setVisibleExe(layer, is_visible) {\n    try {\n        await executeAsModal(async () => {\n            layer.visible = is_visible\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function selectLayersExe(layers) {\n    await executeAsModal(async () => {\n        await selectLayers(layers)\n    })\n}\nasync function selectGroup(layer) {\n    await unselectActiveLayers()\n    layer.parent.selected = true\n}\nasync function collapseGroup(layer) {\n    await selectGroup(layer)\n    await app.activeDocument.activeLayers[0].merge()\n}\n\nasync function createMaskCommand() {\n    const batchPlay = require('photoshop').action.batchPlay\n\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'make',\n                new: {\n                    _class: 'channel',\n                },\n                at: {\n                    _ref: 'channel',\n                    _enum: 'channel',\n                    _value: 'mask',\n                },\n                using: {\n                    _enum: 'userMaskEnabled',\n                    _value: 'revealSelection',\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n}\n\nasync function createMaskExe() {\n    const { executeAsModal } = require('photoshop').core\n    await executeAsModal(createMaskCommand)\n}\n\n//unselect the rectangular marquee selection area\nasync function unSelectMarqueeCommand() {\n    const batchPlay = require('photoshop').action.batchPlay\n\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _enum: 'ordinal',\n                    _value: 'none',\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n\n    return result\n}\nasync function unSelectMarqueeExe() {\n    try {\n        await executeAsModal(unSelectMarqueeCommand)\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//REFACTOR: move to selection.js\nasync function selectMarqueeRectangularToolExe() {\n    async function selectMarqueeRectangularToolCommand() {\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'select',\n                    _target: [\n                        {\n                            _ref: 'marqueeRectTool',\n                        },\n                    ],\n                    _options: {\n                        dialogOptions: 'dontDisplay',\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n        return result\n    }\n    await executeAsModal(async () => {\n        await selectMarqueeRectangularToolCommand()\n    })\n}\n\nasync function promptForMarqueeTool() {\n    console.warn('promptForMarqueeTool is deprecated use Notification class')\n    ;(async () => {\n        const r1 = await dialog_box.prompt(\n            'Please Select a Rectangular Area',\n            'You Forgot to select a Rectangular Area',\n            ['Cancel', 'Rectangular Marquee']\n        )\n        if ((r1 || 'Rectangular Marquee') !== 'Rectangular Marquee') {\n            /* cancelled or No */\n            console.log('cancel')\n        } else {\n            /* Yes */\n            console.log('Rectangular Marquee')\n            selectMarqueeRectangularToolExe()\n        }\n    })()\n}\n\nasync function selectLayerChannelCommand() {\n    //   const result = await batchPlay(\n    //     [\n    //       {\n    //         _obj: 'set',\n    //         _target: [\n    //           {\n    //             _ref: 'channel',\n    //             _property: 'selection'\n    //           }\n    //         ],\n    //         to: {\n    //           _ref: [\n    //             {\n    //               _ref: 'channel',\n    //               _enum: 'channel',\n    //               _value: 'transparencyEnum'\n    //             },\n    //             {\n    //               _ref: 'layer',\n    //               _name: 'Group 5'\n    //             }\n    //           ]\n    //         },\n    //         _options: {\n    //           dialogOptions: 'dontDisplay'\n    //         }\n    //       }\n    //     ],\n    //     {\n    //       synchronousExecution: false,\n    //       modalBehavior: 'execute'\n    //     }\n    //   )\n    const batchPlay = require('photoshop').action.batchPlay\n\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _ref: 'channel',\n                    _enum: 'channel',\n                    _value: 'transparencyEnum',\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n}\n\nasync function getSelectionInfoCommand() {\n    // console.warn('getSelectionInfoCommand is deprecated use SelectionInfoDesc')\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'get',\n                _target: [\n                    {\n                        _property: 'selection',\n                    },\n                    {\n                        _ref: 'document',\n                        _id: app.activeDocument._id,\n                    },\n                ],\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n\n    return result\n}\n\nfunction isSelectionValid(selection) {\n    // console.warn(\n    //     'isSelectionValid is deprecated use selection.isSelectionValid instead'\n    // )\n    if (\n        selection && // check if the selection is defined\n        selection.hasOwnProperty('left') &&\n        selection.hasOwnProperty('right') &&\n        selection.hasOwnProperty('top') &&\n        selection.hasOwnProperty('bottom')\n    ) {\n        return true\n    }\n\n    return false\n}\n\nasync function getSelectionInfoExe() {\n    // console.log('getSelectionInfo was called')\n    // console.warn(\n    //     'getSelectionInfoExe is deprecated use selection.getSelectionInfoExe instead'\n    // )\n    try {\n        const selection = (await executeAsModal(getSelectionInfoCommand))[0]\n            .selection\n\n        if (isSelectionValid(selection)) {\n            let selection_info = {\n                left: selection.left._value,\n                right: selection.right._value,\n                bottom: selection.bottom._value,\n                top: selection.top._value,\n                height: selection.bottom._value - selection.top._value,\n                width: selection.right._value - selection.left._value,\n            }\n            // console.dir({selection_info})\n            return selection_info\n        }\n    } catch (e) {\n        console.warn('selection info error', e)\n    }\n}\n\nasync function reSelectMarqueeCommand(selectionInfo) {\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _obj: 'rectangle',\n                    top: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.top,\n                    },\n                    left: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.left,\n                    },\n                    bottom: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.bottom,\n                    },\n                    right: {\n                        _unit: 'pixelsUnit',\n                        _value: selectionInfo.right,\n                    },\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n}\nasync function reSelectMarqueeExe(selectionInfo) {\n    try {\n        if (isSelectionValid(selectionInfo)) {\n            //only try to reactivate the selection area if it is valid\n            await executeAsModal(async () => {\n                await reSelectMarqueeCommand(selectionInfo)\n            })\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function snapshot_layer() {\n    let psAction = require('photoshop').action\n    // const ids = (await app.activeDocument.activeLayers).map(layer => layer.id)\n    const ids = await app.activeDocument.layers.map((layer) => layer.id)\n    let command = [\n        // Select All Layers current layer\n        {\n            _obj: 'selectAllLayers',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n        },\n        // Duplicate current layer\n        // {\"ID\":[459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513],\"_obj\":\"duplicate\",\"_target\":[{\"_enum\":\"ordinal\",\"_ref\":\"layer\",\"_value\":\"targetEnum\"}],\"version\":5},\n        {\n            ID: ids,\n            _obj: 'duplicate',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n            // version: 5\n        },\n\n        // Merge Layers\n        { _obj: 'mergeLayersNew' },\n        // Make\n        {\n            _obj: 'make',\n            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },\n            new: { _class: 'channel' },\n            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },\n        },\n        // Set Selection\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },\n        },\n    ]\n    const result = await psAction.batchPlay(command, {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n    console.log('snapshot_layer: result: ', result)\n    return result\n}\nasync function snapshot_layer_new() {\n    //similar to snapshot_layer() but fixes the problem with smart effects\n\n    let psAction = require('photoshop').action\n\n    const ids = await app.activeDocument.layers.map((layer) => layer.id)\n    const selection_info = await getSelectionInfoExe()\n\n    let create_snapshot_layer_command = [\n        // Select All Layers current layer\n        {\n            _obj: 'selectAllLayers',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n        },\n        // Duplicate current layer\n\n        {\n            ID: ids,\n            _obj: 'duplicate',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n            // version: 5\n        },\n\n        // Merge Layers\n        { _obj: 'mergeLayersNew' },\n    ]\n    const result = await psAction.batchPlay(create_snapshot_layer_command, {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n    await reSelectMarqueeExe(selection_info) //reselect the selection area for the mask\n    //make a mask of the selection area\n    const make_mask_command = [\n        // Make\n        {\n            _obj: 'make',\n            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },\n            new: { _class: 'channel' },\n            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },\n        },\n        // // Set Selection\n        // {\n        //     _obj: 'set',\n        //     _target: [{ _property: 'selection', _ref: 'channel' }],\n        //     to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },\n        // },\n    ]\n    const result_2 = await psAction.batchPlay(make_mask_command, {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n    await reSelectMarqueeExe(selection_info) //reselect the selection area again so we don't break other functionality\n\n    console.log('snapshot_layer: result: ', result)\n    return result\n}\n\nasync function snapshot_layerExe() {\n    try {\n        await executeAsModal(\n            async () => {\n                await snapshot_layer_new()\n            },\n            {\n                commandName: `Canvas Snapshot...`,\n            }\n        )\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nasync function snapshot_layer_no_slide() {\n    let psAction = require('photoshop').action\n    // const ids = (await app.activeDocument.activeLayers).map(layer => layer.id)\n    const ids = await app.activeDocument.layers.map((layer) => layer.id)\n    let command = [\n        // Select All Layers current layer\n        {\n            _obj: 'selectAllLayers',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n        },\n        // Duplicate current layer\n        // {\"ID\":[459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513],\"_obj\":\"duplicate\",\"_target\":[{\"_enum\":\"ordinal\",\"_ref\":\"layer\",\"_value\":\"targetEnum\"}],\"version\":5},\n        {\n            ID: ids,\n            _obj: 'duplicate',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n            // version: 5\n        },\n\n        // // Merge Layers\n        // { _obj: 'mergeLayersNew' },\n        // // Make\n        // {\n        //     _obj: 'make',\n        //     at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },\n        //     new: { _class: 'channel' },\n        //     using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },\n        // },\n        // // Set Selection\n        // {\n        //     _obj: 'set',\n        //     _target: [{ _property: 'selection', _ref: 'channel' }],\n        //     to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },\n        // },\n    ]\n    const result = await psAction.batchPlay(command, {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n    console.log('snapshot_layer: result: ', result)\n    return result\n}\n\nasync function snapshot_layer_no_slide_Exe() {\n    try {\n        await executeAsModal(\n            async () => {\n                await snapshot_layer_no_slide()\n            },\n            {\n                commandName: 'Action Commands',\n            }\n        )\n    } catch (e) {\n        console.error(e)\n    }\n}\n\n// await runModalFunction();\n\nasync function fillAndGroup() {\n    let result\n    let psAction = require('photoshop').action\n\n    // let newCommand =[\n    //   // snapshotLayer\n\n    //   // makeGroupCommand\n\n    //   // Make fill layer\n    //   {\"_obj\":\"make\",\"_target\":[{\"_ref\":\"contentLayer\"}],\"using\":{\"_obj\":\"contentLayer\",\"type\":{\"_obj\":\"solidColorLayer\",\"color\":{\"_obj\":\"RGBColor\",\"blue\":255.0,\"grain\":255.0,\"red\":255.0}}}},\n\n    // ]\n\n    let command = [\n        // Make fill layer\n        {\n            _obj: 'make',\n            _target: [{ _ref: 'contentLayer' }],\n            using: {\n                _obj: 'contentLayer',\n                type: {\n                    _obj: 'solidColorLayer',\n                    color: {\n                        _obj: 'RGBColor',\n                        blue: 255.0,\n                        grain: 255.0,\n                        red: 255.0,\n                    },\n                },\n            },\n        },\n        // Move current layer\n        // {\"_obj\":\"move\",\"_target\":[{\"_enum\":\"ordinal\",\"_ref\":\"layer\",\"_value\":\"targetEnum\"}],\"adjustment\":false,\"layerID\":[17],\"to\":{\"_index\":7,\"_ref\":\"layer\"},\"version\":5},\n        // Select layer “Layer 4 copy”\n        // {\"_obj\":\"select\",\"_target\":[{\"_name\":\"Layer 4 copy\",\"_ref\":\"layer\"}],\"layerID\":[17,15],\"makeVisible\":false,\"selectionModifier\":{\"_enum\":\"selectionModifierType\",\"_value\":\"addToSelectionContinuous\"}},\n        // Make Group\n        // {\"_obj\":\"make\",\"_target\":[{\"_ref\":\"layerSection\"}],\"from\":{\"_enum\":\"ordinal\",\"_ref\":\"layer\",\"_value\":\"targetEnum\"},\"layerSectionEnd\":19,\"layerSectionStart\":18,\"name\":\"Group 1\"}\n    ]\n    const snapshotLayer = await app.activeDocument.activeLayers[0]\n    await makeGroupCommand()\n    const groupLayer = app.activeDocument.activeLayers[0]\n    result = await psAction.batchPlay(command, {})\n    const fillLayer = app.activeDocument.activeLayers[0]\n    snapshotLayer.moveAbove(fillLayer)\n    // await app.activeDocument.activeLayers[0].moveAbove()\n    // const layerIDs = []\n    // const to_index = await getIndexCommand(groupLayer.id)\n    // await moveToGroupCommand(to_index, layerIDs)\n}\n\nasync function fillAndGroupExe() {\n    await require('photoshop').core.executeAsModal(fillAndGroup, {\n        commandName: 'Action Commands',\n    })\n}\nasync function fastSnapshot() {\n    await snapshot_layerExe()\n    await fillAndGroupExe()\n}\n\nfunction layerToFileName(layer, session_id) {\n    file_name = `${layer.name}_${layer.id}_${session_id}`\n    return file_name\n}\nfunction layerNameToFileName(layer_name, layer_id, session_id) {\n    file_name = `${layer_name}_${layer_id}_${session_id}`\n    return file_name\n}\n\nasync function cleanLayers(layers) {\n    // g_init_image_related_layers = {}\n    // g_mask_related_layers = {}\n\n    console.log('cleanLayers() -> layers:', layers)\n    for (layer of layers) {\n        try {\n            if (layer_util.Layer.doesLayerExist(layer)) {\n                await executeAsModal(async () => {\n                    await layer.delete()\n                })\n            }\n        } catch (e) {\n            console.warn(\n                'warning attempting to a delete layer,layer.name: ',\n                layer.name,\n                layer,\n                e\n            )\n            continue\n        }\n    }\n    return []\n}\n\n// async function cleanLayersOutpaint(layers){\n//   //delete group mask layer\n//   //delete mask layer\n//   //delete group init image layer\n//   //delete init image layer (snapshot layer)\n//   //delete fill layer\n\n//   for (layer of layers){\n//     try {\n//       await executeAsModal(async ()=>{await layer.delete()})}\n//       catch(e){\n//         console.warn(\"warning attempting to a delete layer: \",e)\n//       }\n//   }\n\n// return []\n// }\n// async function cleanLayersInpaint(layers){\n//   //delete group mask layer\n//   //delete white mask layer\n//   //delete the black fill layer\n//   //delete init image layer (snapshot layer)\n\n//   for (layer of layers){\n//     await executeAsModal(async ()=>{await layer.delete()})\n//   }\n\n// return []\n// }\nasync function createClippingMaskExe() {\n    const batchPlay = require('photoshop').action.batchPlay\n\n    async function createClippingMaskCommand() {\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'make',\n                    new: {\n                        _class: 'channel',\n                    },\n                    at: {\n                        _ref: 'channel',\n                        _enum: 'channel',\n                        _value: 'mask',\n                    },\n                    using: {\n                        _enum: 'userMaskEnabled',\n                        _value: 'revealSelection',\n                    },\n                    _options: {\n                        dialogOptions: 'dontDisplay',\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n    }\n\n    await executeAsModal(async () => {\n        await createClippingMaskCommand()\n    })\n}\n//REFACTOR: delete and replace with getSelectionInfoExe()\nasync function checkIfSelectionAreaIsActive() {\n    try {\n        let isSelectionAreaValid = await getSelectionInfoExe()\n        return isSelectionAreaValid\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function saveUniqueDocumentIdExe(new_id) {\n    const batchPlay = require('photoshop').action.batchPlay\n\n    async function saveUniqueDocumentIdCommand() {\n        const batchPlay = require('photoshop').action.batchPlay\n\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'set',\n                    _target: [\n                        {\n                            _ref: 'property',\n                            _property: 'fileInfo',\n                        },\n                        {\n                            _ref: 'document',\n                            _enum: 'ordinal',\n                            _value: 'targetEnum',\n                        },\n                    ],\n                    to: {\n                        _obj: 'fileInfo',\n                        caption: new_id,\n                        keywords: [new_id],\n                    },\n                    _options: {\n                        dialogOptions: 'dontDisplay',\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n    }\n\n    await executeAsModal(async () => {\n        await saveUniqueDocumentIdCommand()\n    })\n}\n\nasync function readUniqueDocumentIdExe() {\n    const batchPlay = require('photoshop').action.batchPlay\n\n    async function readUniqueDocumentIdCommand() {\n        const batchPlay = require('photoshop').action.batchPlay\n\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'get',\n                    _target: [\n                        {\n                            _ref: 'property',\n                            _property: 'fileInfo',\n                        },\n                        {\n                            _ref: 'document',\n                            _enum: 'ordinal',\n                            _value: 'targetEnum',\n                        },\n                    ],\n                    // to: {\n                    //   _obj: 'fileInfo',\n                    //   caption: new_id,\n                    //   keywords: [new_id]\n                    // },\n                    _options: {\n                        dialogOptions: 'dontDisplay',\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n        console.log('readUniqueDocumentIdCommand: result ', result)\n        return result\n    }\n\n    let uniqueDocumentId = ''\n    try {\n        await executeAsModal(async () => {\n            uniqueDocumentId = (await readUniqueDocumentIdCommand())[0].fileInfo\n                .caption\n            if (typeof uniqueDocumentId === 'string') {\n                uniqueDocumentId = uniqueDocumentId.trim()\n            }\n        })\n    } catch (e) {\n        console.warn('readUniqueDocumentIdExe: ', e)\n        uniqueDocumentId = ''\n    }\n\n    return uniqueDocumentId\n}\n\nconst readPng = async (image_name) => {\n    //it will save the document then read it. store it in memory\n    // image_name = 'test.png'\n    try {\n        let img_buffer\n        await executeAsModal(\n            async (control) => {\n                const folder = await fs.getTemporaryFolder()\n                // const pluginFolder = await fs.getPluginFolder()\n\n                // let init_images_dir = await pluginFolder.getEntry(\n                //     './server/python_server/init_images'\n                // )\n\n                const file = await folder.createFile(image_name, {\n                    overwrite: true,\n                })\n\n                const currentDocument = app.activeDocument\n                await currentDocument.saveAs.png(\n                    file,\n                    // {\n                    //   compression: 6,\n                    // },\n                    null,\n                    true\n                )\n\n                const arrayBuffer = await file.read({ format: formats.binary })\n                // console.log(arrayBuffer, 'arrayBuffer') ;\n                img_buffer = arrayBuffer\n            },\n\n            { commandName: 'readPng' }\n        )\n\n        return img_buffer\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function selectCanvasCommand() {\n    // const result = await batchPlay(\n    // [\n    //    {\n    //       _obj: \"historyStateChanged\",\n    //       documentID: 1044,\n    //       ID: 1058,\n    //       name: \"Select Canvas\",\n    //       hasEnglish: true,\n    //       itemIndex: 7,\n    //       commandID: 1017,\n    //       _options: {\n    //          dialogOptions: \"dontDisplay\"\n    //       }\n    //    }\n    // ],{\n    //    synchronousExecution: true,\n    //    modalBehavior: \"execute\"\n    // });\n\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _enum: 'ordinal',\n                    _value: 'allEnum',\n                },\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n\n    return result\n}\nasync function selectCanvasExe() {\n    await executeAsModal(\n        async () => {\n            await selectCanvasCommand()\n        },\n        { commandName: 'selectCanvasExe' }\n    )\n}\nasync function newExportPng(layer, image_name, width, height) {\n    //store layers we want to export in variables\n    // let layerToExports =\n    // create new document\n    // duplicate the layers to the new documnet\n    //select the layer channel selectLayerChannelCommand\n    //document.crop\n    //export using readPng()\n\n    try {\n        //get the active layers\n        // const layersToExport = app.activeDocument.activeLayers\n\n        //create new document\n        // let exportDoc = await executeAsModal(app.documents.add)\n        let exportDoc\n        const makeDoc = async () => {\n            let exportDoc = await app.documents.add({\n                width: width,\n                height: height,\n                resolution: await app.activeDocument.resolution,\n                mode: 'RGBColorMode',\n                fill: 'transparent',\n            })\n        }\n        let image_buffer\n        await executeAsModal(\n            async () => {\n                // await app.documents.add()\n                await makeDoc()\n                exportDoc = app.activeDocument\n\n                console.log('exportDoc.id: ', exportDoc.id)\n                // for (layer of layersToExport) {\n\n                console.log(layer.id)\n                const dupLayer = await layer.duplicate(exportDoc)\n                await selectLayers([dupLayer])\n                // await selectLayerChannelCommand()\n                await selectCanvasExe()\n                const canvas_selection_info = await getSelectionInfoExe()\n                await layerToSelection(canvas_selection_info)\n                // const selection_info = await getSelectionInfoExe()\n                // await exportDoc.crop(selection_info)\n                // export_image_name = `${layer.name}.png`\n                image_buffer = await readPng(image_name)\n                await exportDoc.closeWithoutSaving()\n            },\n            { commandName: 'NewExportPng' }\n        )\n        return image_buffer\n        // }\n    } catch (e) {\n        console.error(`newExportPng error: ,${e}`)\n    }\n}\n\nasync function tempExportPng(layer, image_name, width, height) {\n    //store layers we want to export in variables\n    // let layerToExports =\n    // create new document\n    // duplicate the layers to the new documnet\n    //select the layer channel selectLayerChannelCommand\n    //document.crop\n    //export using readPng()\n\n    try {\n        //get the active layers\n        // const layersToExport = app.activeDocument.activeLayers\n\n        //create new document\n        // let exportDoc = await executeAsModal(app.documents.add)\n        let exportDoc\n        const makeDoc = async () => {\n            let exportDoc = await app.documents.add({\n                width: width,\n                height: height,\n                resolution: await app.activeDocument.resolution,\n                mode: 'RGBColorMode',\n                fill: 'transparent',\n            })\n        }\n        await executeAsModal(\n            async () => {\n                // await app.documents.add()\n                await makeDoc()\n                exportDoc = app.activeDocument\n\n                console.log('exportDoc.id: ', exportDoc.id)\n                // for (layer of layersToExport) {\n\n                console.log(layer.id)\n                const dupLayer = await layer.duplicate(exportDoc)\n                await selectLayers([dupLayer])\n                // await selectLayerChannelCommand()\n                await selectCanvasExe()\n                const canvas_selection_info = await getSelectionInfoExe()\n                await layerToSelection(canvas_selection_info)\n                // const selection_info = await getSelectionInfoExe()\n                // await exportDoc.crop(selection_info)\n                // export_image_name = `${layer.name}.png`\n                await readPng(image_name)\n                await exportDoc.closeWithoutSaving()\n            },\n            { commandName: 'tempExportPng' }\n        )\n        // }\n    } catch (e) {\n        console.error(`newExportPng error: ,${e}`)\n    }\n}\nasync function mergeVisibleCommand() {\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'mergeVisible',\n                duplicate: true,\n                _isCommand: true,\n                // \"_options\": {\n                //   // \"dialogOptions\": \"dontDisplay\"\n                // }\n            },\n        ],\n        {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        }\n    )\n\n    return result\n}\n\nasync function mergeVisibleExe() {\n    await executeAsModal(async () => {\n        await mergeVisibleCommand()\n    })\n}\n\nasync function layerToSelection(selection_info) {\n    //store active layer for later\n\n    try {\n        //Store selection info\n        //unSelect\n        //move layer\n        //scale layer\n        //Select from selection info\n        // let selection_info = await getSelectionInfo()\n\n        console.log('selection_info:', selection_info)\n\n        console.log('unSelect')\n\n        function getLayerSize(layer) {\n            console.log('layer.bounds:')\n            console.dir(layer.bounds)\n            const bounds = layer.bounds\n            const height = bounds.bottom - bounds.top\n            const width = bounds.right - bounds.left\n            return {\n                height: height,\n                width: width,\n                left: bounds.left,\n                right: bounds.right,\n                top: bounds.top,\n                bottom: bounds.bottom,\n            }\n        }\n        //scale layer\n        async function scaleLayer(layer, selection_info) {\n            console.log('scaleLayer got called')\n            // const activeLayer = getActiveLayer()\n            // const activeLayer = await app.activeDocument.activeLayers[0]\n\n            let layer_info = getLayerSize(layer)\n            scale_x_ratio = (selection_info.width / layer_info.width) * 100\n            scale_y_ratio = (selection_info.height / layer_info.height) * 100\n            console.log('scale_x_y_ratio:', scale_x_ratio, scale_y_ratio)\n            // await layer.scale(\n            //     scale_x_ratio,\n            //     scale_y_ratio,\n            //     constants.ResampleMethod.BILINEAR\n            // )\n            await layer_util.Layer.resizeImageExe(scale_x_ratio, scale_y_ratio)\n        }\n\n        async function moveLayerExe(layerToMove, selection_info) {\n            let layer_info = getLayerSize(layerToMove)\n            top_dist = layer_info.top - selection_info.top\n            left_dist = layer_info.left - selection_info.left\n            await layerToMove.translate(-left_dist, -top_dist)\n        }\n        // const activeLayer = await getActiveLayer()\n\n        //store all active layers\n        const activeLayers = await app.activeDocument.activeLayers\n        await unSelectMarqueeExe()\n        // await executeAsModal(unSelect,  {'commandName': 'unSelect'})\n        // await executeAsModal(scaleLayer,  {'commandName': 'scaleLayer'})\n\n        await executeAsModal(\n            async () => {\n                for (let layer of activeLayers) {\n                    await selectLayers([layer]) // make sure only one layer is selected\n                    await scaleLayer(layer, selection_info) //scale to selection size\n                    await moveLayerExe(layer, selection_info) //move to selection\n                }\n            },\n            { commandName: 'moveLayerExe' }\n        )\n\n        // await reselect(selection_info)\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction executeCommandExe(commandFunc) {\n    try {\n        ;(async () => {\n            await executeAsModal(async () => {\n                await commandFunc()\n            })\n        })()\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function executeDescExe(Desc) {\n    try {\n        await executeAsModal(async () => {\n            const result = await batchPlay([Desc], {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            })\n            console.log(result)\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\nmodule.exports = {\n    createSolidLayer,\n    createEmptyGroup,\n    getLayerIndex,\n    collapseGroup,\n    moveToGroupCommand,\n    MoveToGroupExe,\n    selectLayers,\n    selectLayersExe,\n    unselectActiveLayers,\n    unselectActiveLayersExe,\n    createMaskExe,\n    getSelectionInfoExe,\n    unSelectMarqueeCommand,\n    unSelectMarqueeExe,\n    reSelectMarqueeExe,\n    selectLayerChannelCommand,\n    snapshot_layer,\n    snapshot_layerExe,\n    fillAndGroupExe,\n    fastSnapshot,\n\n    layerToFileName,\n    layerNameToFileName,\n\n    cleanLayers,\n    createClippingMaskExe,\n    checkIfSelectionAreaIsActive,\n    selectMarqueeRectangularToolExe,\n    promptForMarqueeTool,\n    saveUniqueDocumentIdExe,\n    readUniqueDocumentIdExe,\n    newExportPng,\n    mergeVisibleExe,\n    selectCanvasExe,\n    layerToSelection,\n    isSelectionValid,\n    snapshot_layer_no_slide_Exe,\n    setVisibleExe,\n\n    executeCommandExe,\n    executeDescExe,\n    getSelectionInfoCommand,\n}\n"
  },
  {
    "path": "requirements.txt",
    "content": "anyio==3.6.2\nasyncio==3.4.3\ncertifi==2022.12.7\ncharset-normalizer==2.1.1\nclick==8.1.7\nfastapi==0.88.0\nh11==0.14.0\nhttpcore==0.16.3\nhttptools==0.5.0\nhttpx==0.25.1\nidna==3.4\nPillow==9.3.0\npydantic==1.10.2\npython-dotenv==0.21.0\nPyYAML==6.0\nrequests==2.28.1\nrfc3986==1.5.0\nsniffio==1.3.0\nstarlette==0.22.0\ntyping_extensions==4.4.0\nurllib3==1.26.13\nuvicorn==0.20.0\n# uvloop==0.17.0\nwatchfiles==0.18.1\nwebsockets==10.4\nduckduckgo_search==3.9.9\n"
  },
  {
    "path": "scripts/main.py",
    "content": "from modules import scripts, processing, shared, images, devices, ui, lowvram\nimport gradio\nimport requests\nimport time\nimport PIL.Image\nimport base64\nimport io\nimport os.path\nimport numpy\nimport itertools\nimport gradio as gr\nimport torch\nfrom fastapi import FastAPI\nfrom fastapi import APIRouter, Request\nfrom fastapi.responses import StreamingResponse\nfrom modules import script_callbacks, scripts, shared\n\n\nimport sys\npython_server_dir = 'server/python_server'\nextension_dir = scripts.basedir()\npython_server_full_path = os.path.join(extension_dir,python_server_dir)\nprint(\"python_server_full_path: \",python_server_full_path)\nsys.path.insert(0, python_server_full_path)\nimport search\nimport img2imgapi\nimport serverMain\n\nrouter = APIRouter()\n\n# @router.get(\"/config\")\n# async def get_state():\n#     print(\"hello get /config auto-photoshop-sd\")\n#     res = \"hello get /config auto-photoshop-sd\"\n#     return {\"res\": res}\n\n@router.post('/search/image/')\nasync def searchImage(request:Request):\n    try:\n        json = await request.json()\n    except: \n        json = {}\n    \n\n    try:\n        keywords = json.get('keywords','cute cats') \n        images = await search.imageSearch(keywords)\n        print(images)\n        \n        \n        return {\"images\":images}\n    except:\n        print(\"keywords\",keywords)\n        # print(f'{request}')\n    return {\"error\": \"error message: can't preform an image search\"}\n\n\n@router.post('/mask/expansion/')\nasync def maskExpansionHandler(request:Request):\n    try:\n        json = await request.json()\n    except: \n        json = {}\n    \n    # print(\"mask expansion json :\",json)\n    try:\n        # keywords = json.get('keywords','cute dogs') \n        base64_mask_image = json['mask']\n        mask_expansion = json['mask_expansion']\n        blur = json['blur']\n        #convert base64 to img\n        \n        await img2imgapi.base64ToPng(base64_mask_image,\"original_mask.png\")#save a copy of the mask\n\n        mask_image = img2imgapi.b64_2_img(base64_mask_image)\n        \n        expanded_mask_img = img2imgapi.maskExpansion(mask_image,mask_expansion,blur)\n        base64_expanded_mask_image = img2imgapi.img_2_b64(expanded_mask_img)\n        await img2imgapi.base64ToPng(base64_expanded_mask_image,\"expanded_mask.png\")#save a copy of the mask\n\n\n        return {\"mask\":base64_expanded_mask_image}\n    \n    except:\n        # print(\"request\",request)\n        raise Exception(f\"couldn't preform mask expansion\",json)\n    # return response\n    return {\"error\": \"error message: can't preform an mask expansion\"}\n\n\n\ndef on_app_started(demo: gr.Blocks, app: FastAPI):\n    # print(\"hello on_app_started auto-photoshop-plugin\")\n  \n    if shared.cmd_opts.api:\n        app.include_router(serverMain.router, prefix=\"/sdapi/auto-photoshop-sd\", tags=['Auto Photoshop SD Plugin API'])\n        # app.include_router(router, prefix=\"/sdapi/auto-photoshop-sd\", tags=['Auto Photoshop SD Plugin API'])\n\n        \n    else:\n        print(\"COMMANDLINE_ARGS does not contain --api, API won't be mounted.\")\n        \n        # logger.warning(\"COMMANDLINE_ARGS does not contain --api, API won't be mounted.\")\n    # if you wanted to do anything massive to the UI, you could modify demo, but why?\n\nscript_callbacks.on_app_started(on_app_started)"
  },
  {
    "path": "scripts/test.py",
    "content": "# import sys\n# sys.path.insert(0, 'server/python_server')\n# import search\n\n# print(\"hello test.py\")  "
  },
  {
    "path": "sdapi_py_re.js",
    "content": "const { getDummyBase64, getDummyBase64_2 } = require('./utility/dummy')\nconst { base64ToBase64Url } = require('./utility/general')\n\nconst py_re = require('./utility/sdapi/python_replacement')\nconst Enum = require('./enum')\n\nconst api = require('./utility/api')\n//javascript plugin can't read images from local directory so we send a request to local server to read the image file and send it back to plugin as image string base64\n\n//REFACTOR: move this function to io.js\nasync function requestSavePng(base64_image, image_name) {\n    try {\n        console.log('requestSavePng():')\n\n        const uniqueDocumentId = await getUniqueDocumentId()\n        const folder = `${uniqueDocumentId}/init_images`\n        const init_entry = await getInitImagesDir()\n        io.saveFileInSubFolder(base64_image, folder, image_name)\n        console.warn('this function is deprecated')\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\nasync function requestTxt2Img(payload) {\n    try {\n        console.log('requestTxt2Img(): about to send a fetch request')\n\n        let json = await py_re.txt2ImgRequest(payload)\n        console.log('requestTxt2Img json:', json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\n\n//Refactor: move to modes.ts\nasync function requestImg2Img(payload) {\n    console.log('requestImg2Img(): about to send a fetch request')\n    try {\n        let json = await py_re.img2ImgRequest(g_sd_url, payload)\n        console.log('requestImg2Img json:')\n        console.dir(json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\n\n//Refactor: move to progress.ts\nasync function requestProgress() {\n    try {\n        console.log('requestProgress: ')\n\n        const full_url = `${g_sd_url}/sdapi/v1/progress?skip_current_image=false`\n        let request = await fetch(full_url)\n        json = await request.json()\n        // console.log('progress json:', json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        // console.log('json: ', json)\n    }\n    return null\n}\n\nasync function requestInterrupt() {\n    const full_url = `${g_sd_url}/sdapi/v1/interrupt`\n    try {\n        console.log('requestInterrupt: ')\n\n        payload = ''\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            // body: JSON.stringify(payload)\n            // \"body\": payload\n        })\n\n        console.log('interrupt request:', request)\n        let json = await request.json()\n\n        return json\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function changeSdUrl(new_sd_url) {\n    // version = \"v0.0.0\"\n    console.log('changeSdUrl: new_sd_url:', new_sd_url)\n    try {\n        payload = {\n            sd_url: new_sd_url,\n        }\n\n        // const full_url = `${g_sd_url}/sd_url/`\n        // console.log('changeSdUrl: payload: ', payload)\n        // let request = await fetch(full_url, {\n        //     method: 'POST',\n        //     headers: {\n        //         Accept: 'application/json',\n        //         'Content-Type': 'application/json',\n        //     },\n        //     body: JSON.stringify(payload),\n        // })\n\n        g_sd_url = new_sd_url\n        // console.log('changeSdUrl: request: ', request)\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n// function printTheJSONInPrettyFormat(json) {\n//   // var badJSON = document.getElementById('prettyJSONFormat').value;\n//   // var parseJSON = JSON.parse(badJSON);\n//   // var JSONInPrettyFormat = JSON.stringify(json, undefined, 4);\n//   // return\n// }\nasync function loadHistory(uniqueDocumentId) {\n    let json = {}\n    try {\n        payload = {\n            uniqueDocumentId: uniqueDocumentId,\n        }\n        json = await py_re.loadHistory(payload)\n    } catch (e) {\n        console.warn(e)\n    }\n\n    return [json['image_paths'], json['metadata_jsons'], json['base64_images']]\n}\nasync function loadPromptShortcut() {\n    let prompt_shortcut_json = {}\n    try {\n        prompt_shortcut_json = await py_re.loadPromptShortcut(\n            'prompt_shortcut.json'\n        )\n        // console.log('loadPromptShortcut:', prompt_shortcut_json)\n    } catch (e) {\n        console.warn(e)\n        prompt_shortcut_json = {}\n    }\n    return prompt_shortcut_json\n}\n\nasync function savePromptShortcut(prompt_shortcut) {\n    let json = prompt_shortcut\n    try {\n        await py_re.savePromptShortcut(json, 'prompt_shortcut.json')\n        console.log('savePromptShortcut:', json)\n        // console.log('loadPromptShortcut: request: ',request)\n    } catch (e) {\n        console.warn(e)\n    }\n\n    return json['prompt_shortcut']\n}\n\nasync function requestGetConfig() {\n    console.log('requestGetConfig: ')\n    let json = []\n    const full_url = `${g_sd_url}/config`\n    try {\n        let request = await fetch(full_url)\n        json = await request.json()\n\n        console.dir(json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\nasync function requestGetOptions() {\n    console.log('requestGetOptions: ')\n    let json = null\n    const full_url = `${g_sd_url}/sdapi/v1/options`\n    try {\n        let request = await fetch(full_url)\n        if (request.status === 404) {\n            return null\n        }\n\n        json = await request.json()\n        console.dir(json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\n\nasync function imageSearch(keywords) {\n    let json = {}\n    const extension_url = py_re.getExtensionUrl()\n\n    const full_url = `${extension_url}/search/image/`\n    try {\n        payload = {\n            keywords: keywords,\n        }\n\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n        })\n\n        json = await request.json()\n        console.log('imageSearch:', json)\n\n        return json['images']\n    } catch (e) {\n        console.warn(e)\n    }\n    return []\n}\n\n// async function requestHorde(payload) {\n//     payload = {\n//         prompt: 'string',\n//         params: {\n//             sampler_name: 'k_lms',\n//             toggles: [1, 4],\n//             cfg_scale: 5,\n//             denoising_strength: 0.75,\n//             seed: 'string',\n//             height: 512,\n//             width: 512,\n//             seed_variation: 1,\n//             post_processing: ['GFPGAN'],\n//             karras: false,\n//             tiling: false,\n//             steps: 30,\n//             n: 1,\n//         },\n//         nsfw: false,\n//         trusted_workers: true,\n//         censor_nsfw: false,\n//         workers: ['4c79ab19-8e6c-4054-83b3-773b7ce71ece'],\n//         models: ['stable_diffusion'],\n//         // source_image: 'string',\n//         // source_processing: 'img2img',\n//         // source_mask: 'string',\n//         r2: true,\n//         shared: false,\n//     }\n//     try {\n//         console.log('requestHorde():')\n\n//         const full_url = 'https://stablehorde.net/api/v2/generate/async'\n//         // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n//         console.log(full_url)\n\n//         let request = await fetch(full_url, {\n//             method: 'POST',\n//             headers: {\n//                 Accept: 'application/json',\n//                 'Content-Type': 'application/json',\n//                 apikey: '0000000000',\n//                 // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',\n//                 'Client-Agent': 'unknown:0:unknown',\n//             },\n//             body: JSON.stringify(payload),\n//         })\n\n//         let json = await request.json()\n//         console.log('requestHorde json:', json)\n\n//         return json\n//     } catch (e) {\n//         console.warn(e)\n//         return {}\n//     }\n// }\n// async function requestHordeCheck(id) {\n//     try {\n//         console.log('requestHordeCheck():')\n//         const base_url = 'https://stablehorde.net/api/v2/generate/check'\n\n//         const full_url = `${base_url}/${id}`\n//         // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n//         console.log(full_url)\n//         const payload = {}\n//         let request = await fetch(full_url, {\n//             method: 'GET',\n//             headers: {\n//                 Accept: 'application/json',\n//                 'Content-Type': 'application/json',\n//                 // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',\n//                 'Client-Agent': 'unknown:0:unknown',\n//             },\n//         })\n\n//         let json = await request.json()\n//         console.log('requestHordeCheck json:', json)\n\n//         return json\n//     } catch (e) {\n//         console.warn(e)\n//         return {}\n//     }\n// }\n\n// async function requestHordeStatus(id) {\n//     try {\n//         console.log('requestHordeStatus():')\n//         const base_url = 'https://stablehorde.net/api/v2/generate/status'\n\n//         const full_url = `${base_url}/${id}`\n//         // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n//         console.log(full_url)\n//         const payload = {}\n//         let request = await fetch(full_url, {\n//             method: 'GET',\n//             headers: {\n//                 Accept: 'application/json',\n//                 'Content-Type': 'application/json',\n//                 // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',\n//                 'Client-Agent': 'unknown:0:unknown',\n//             },\n//         })\n\n//         let json = await request.json()\n//         console.log('requestHordeStatus json:', json)\n\n//         return json\n//     } catch (e) {\n//         console.warn(e)\n//         return {}\n//     }\n// }\n\nasync function requestExtraSingleImage(payload) {\n    console.log('requestExtraSingleImage(): about to send a fetch request')\n    try {\n        let json = await py_re.extraSingleImageRequest(g_sd_url, payload)\n        console.log('requestExtraSingleImage json:')\n        console.dir(json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\n\nasync function isWebuiRunning() {\n    console.log('isWebuiRunning: ')\n    let json = []\n    const full_url = `${g_sd_url}/user`\n    try {\n        let request = await fetch(full_url)\n        json = await request.json()\n        console.log('json:')\n        console.dir(json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n        return false\n    }\n    return true\n}\n\nmodule.exports = {\n    requestTxt2Img,\n    requestImg2Img,\n\n    requestProgress,\n\n    requestInterrupt,\n\n    changeSdUrl,\n    loadPromptShortcut,\n    savePromptShortcut,\n    loadHistory,\n\n    requestGetConfig,\n    requestGetOptions,\n    imageSearch,\n    requestSavePng,\n    // requestHorde,\n    // requestHordeCheck,\n    // requestHordeStatus,\n    requestExtraSingleImage,\n\n    isWebuiRunning,\n}\n"
  },
  {
    "path": "selection.js",
    "content": "const psapi = require('./psapi')\n\nconst html_manip = require('./utility/html_manip')\nfunction finalWidthHeight(\n    selectionWidth,\n    selectionHeight,\n    minWidth,\n    minHeight\n) {\n    // const minWidth = 512\n    // const minHeight = 512\n\n    // const selectionWidth = 256\n    // const selectionHeight = 1000\n\n    let finalWidth = 0\n    let finalHeight = 0\n\n    if (selectionWidth <= selectionHeight) {\n        //do operation on the smaller dimension\n        const scaleRatio = selectionWidth / minWidth\n\n        finalWidth = minWidth\n        finalHeight = selectionHeight / scaleRatio\n    } else {\n        const scaleRatio = selectionHeight / minHeight\n\n        finalHeight = minHeight\n        finalWidth = selectionWidth / scaleRatio\n    }\n    return [finalWidth, finalHeight]\n}\n\nasync function selectionToFinalWidthHeight(\n    selectionInfo,\n    minWidth = 512,\n    minHeight = 512\n) {\n    // const { getSelectionInfoExe } = require('./psapi')\n    try {\n        // const selectionInfo = await psapi.getSelectionInfoExe()\n        const [finalWidth, finalHeight] = finalWidthHeight(\n            selectionInfo.width,\n            selectionInfo.height,\n            minWidth,\n            minHeight\n        )\n\n        return [\n            parseInt(finalWidth),\n            parseInt(finalHeight),\n            selectionInfo.width,\n            selectionInfo.height,\n        ]\n    } catch (e) {\n        console.warn('you need a rectangular selection', e)\n    }\n}\n\nasync function selectBoundingBox() {\n    let l = await app.activeDocument.activeLayers[0]\n    let bounds = await l.boundsNoEffects\n    let selectionInfo = convertSelectionObjectToSelectionInfo(bounds)\n    await psapi.reSelectMarqueeExe(selectionInfo)\n    return selectionInfo\n}\nfunction convertSelectionObjectToSelectionInfo(selection_obj) {\n    let selection_info = {\n        left: selection_obj._left,\n        right: selection_obj._right,\n        bottom: selection_obj._bottom,\n        top: selection_obj._top,\n        height: selection_obj._bottom - selection_obj._top,\n        width: selection_obj._right - selection_obj._left,\n    }\n    return selection_info\n}\n\nconst SelectionInfoDesc = () => ({\n    _obj: 'get',\n    _target: [\n        {\n            _property: 'selection',\n        },\n        {\n            _ref: 'document',\n            _id: app.activeDocument._id,\n        },\n    ],\n    _options: {\n        dialogOptions: 'dontDisplay',\n    },\n})\n\nasync function createChannelIfNotExists(channelName) {\n    // const photoshop = require('photoshop')\n    // const app = photoshop.app\n    // const batchPlay = photoshop.action.batchPlay\n\n    // // Check if the channel exists\n    // let channelExists = false\n    // for (const channel of app.activeDocument.channels) {\n    //     if (channel.name === channelName) {\n    //         channelExists = true\n    //         break\n    //     }\n    // }\n\n    // // Create the channel if it doesn't exist\n    // if (!channelExists) {\n    //     await batchPlay(\n    //         [\n    //             {\n    //                 _obj: 'make',\n    //                 _target: [\n    //                     {\n    //                         _ref: 'channel',\n    //                     },\n    //                 ],\n    //                 using: {\n    //                     _obj: 'channel',\n    //                     name: channelName,\n    //                 },\n    //             },\n    //         ],\n    //         {}\n    //     )\n    // }\n    if (!app.activeDocument.channels.getByName(channelName)) {\n    }\n}\n\nconst deleteChannel = (channel_name = 'mask') =>\n    app.activeDocument.channels.getByName(channel_name)\n        ? [\n              {\n                  _obj: 'delete',\n                  _target: { _ref: 'channel', _name: channel_name },\n                  options: {\n                      failOnMissingProperty: false,\n                      failOnMissingElement: false,\n                  },\n              },\n          ]\n        : []\nconst makeMaskChannel = (channel_name = 'mask') => ({\n    // _obj: 'set',\n    // _target: { _ref: 'channel', _property: 'selection' },\n    // to: { _ref: 'channel', _name: channel_name },\n\n    _obj: 'duplicate',\n    _target: [\n        {\n            _ref: 'channel',\n            _property: 'selection',\n        },\n    ],\n    name: channel_name,\n    _isCommand: true,\n    options: { failOnMissingProperty: false, failOnMissingElement: false },\n})\nasync function makeMaskChannelExe(channel_name = 'mask') {\n    await executeAsModal(async () => {\n        // const channel = app.activeDocument.channels.getByName(channel_name)\n        // channel?.remove()\n        const result = await batchPlay(\n            [...deleteChannel(channel_name), makeMaskChannel(channel_name)],\n            // [\n            //     {\n            //         _obj: 'duplicate',\n            //         _target: [\n            //             {\n            //                 _ref: 'channel',\n            //                 _property: 'selection',\n            //             },\n            //         ],\n            //         name: channel_name,\n            //         _isCommand: true,\n            //     },\n\n            //     {\n            //         _obj: 'make',\n            //         new: { _class: 'channel' },\n            //         at: { _ref: 'channel', _enum: 'channel', _value: 'mask' },\n            //         using: {\n            //             _enum: 'userMaskEnabled',\n            //             _value: 'revealSelection',\n            //         },\n            //     },\n            // ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n        console.log('result: ', result)\n    })\n}\nasync function multiGetExe() {\n    desc = {\n        _obj: 'multiGet',\n        _target: { _ref: 'layer', _enum: 'ordinal', _value: 'targetEnum' },\n        extendedReference: [['layerID', 'itemIndex', 'count']],\n        options: { failOnMissingProperty: false, failOnMissingElement: false },\n    }\n\n    try {\n        const result = await batchPlay([desc], {\n            modalBehavior: 'execute',\n            synchronousExecution: true,\n        })\n        console.log('multiGetExe result: ', result)\n        // await executeAsModal(async () => {})\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function applyMaskChannelExe(channel_name = 'mask') {\n    await executeAsModal(async () => {\n        const result = await batchPlay(\n            [\n                // SelectionInfoDesc(),\n                // makeMaskChannel(),\n\n                {\n                    _obj: 'set',\n                    _target: { _ref: 'channel', _property: 'selection' },\n                    to: { _ref: 'channel', _name: channel_name },\n                },\n                {\n                    _obj: 'make',\n                    new: { _class: 'channel' },\n                    at: { _ref: 'channel', _enum: 'channel', _value: 'mask' },\n                    using: {\n                        _enum: 'userMaskEnabled',\n                        _value: 'revealSelection',\n                        _name: channel_name,\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n        console.log('result: ', result)\n    })\n}\n\nasync function selectionToChannel(channel_name) {\n    const channelToSelection = {\n        _obj: 'set',\n        _target: { _ref: 'channel', _property: 'selection' },\n        to: { _ref: 'channel', _name: channel_name },\n    }\n    let result\n    try {\n        await executeAsModal(async () => {\n            result = await batchPlay(\n                [\n                    ...deleteChannel(channel_name),\n                    makeMaskChannel(channel_name),\n                    channelToSelection,\n                ],\n                { modalBehavior: 'execute', synchronousExecution: true }\n            )\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n    return result\n}\nasync function createLayerFromMaskChannel(channel_name = 'mask') {\n    await executeAsModal(async () => {\n        const result = await batchPlay(\n            [\n                // SelectionInfoDesc(),\n                // makeMaskChannel(),\n                // {\n                //     _obj: 'set',\n                //     _target: { _ref: 'channel', _property: 'selection' },\n                //     to: { _ref: 'channel', _name: channel_name },\n                // },\n                // {\n                //     _obj: 'make',\n                //     new: { _class: 'channel' },\n                //     at: { _ref: 'channel', _enum: 'channel', _value: 'mask' },\n                //     using: {\n                //         _enum: 'userMaskEnabled',\n                //         _value: 'revealSelection',\n                //         _name: channel_name,\n                //     },\n                // },\n                {\n                    _obj: 'set',\n                    _target: { _ref: 'layer' },\n                    to: { _ref: 'channel', _name: channel_name },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n        console.log('result: ', result)\n    })\n}\n\nasync function channelToSelectionExe(channel_name = 'mask') {\n    const channelToSelection = {\n        _obj: 'set',\n        _target: { _ref: 'channel', _property: 'selection' },\n        to: { _ref: 'channel', _name: channel_name },\n    }\n    try {\n        await executeAsModal(async () => {\n            const result = await batchPlay([channelToSelection], {\n                modalBehavior: 'execute',\n                synchronousExecution: true,\n            })\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction keepRatio(selectionInfo, offset) {\n    // Calculate the current width and height\n    let width = selectionInfo.right - selectionInfo.left\n    let height = selectionInfo.bottom - selectionInfo.top\n\n    // Calculate the new coordinates with the offset\n    selectionInfo.right += offset\n    selectionInfo.left -= offset\n    selectionInfo.bottom += offset\n    selectionInfo.top -= offset\n\n    // Update width and height\n    selectionInfo.width = width + 2 * offset\n    selectionInfo.height = height + 2 * offset\n\n    return selectionInfo\n}\n\nfunction makeSquare(selectionInfo, offset) {\n    // Calculate the current width and height\n    let width = selectionInfo.right - selectionInfo.left\n    let height = selectionInfo.bottom - selectionInfo.top\n\n    // Determine the maximum dimension\n    let maxDim = Math.max(width, height)\n\n    // Calculate the difference for width and height\n    let diffWidth = maxDim - width\n    let diffHeight = maxDim - height\n\n    // Add half the difference to 'right' and 'bottom', subtract the rest from 'left' and 'top'\n    selectionInfo.right += Math.floor(diffWidth / 2) + offset\n    selectionInfo.left -= diffWidth - Math.floor(diffWidth / 2) + offset\n    selectionInfo.bottom += Math.floor(diffHeight / 2) + offset\n    selectionInfo.top -= diffHeight - Math.floor(diffHeight / 2) + offset\n\n    // Update width and height\n    selectionInfo.width = maxDim + 2 * offset\n    selectionInfo.height = maxDim + 2 * offset\n\n    return selectionInfo\n}\n\nasync function inpaintLassoInitImageAndMask(\n    channel_name = 'mask',\n    offset = 0,\n    make_square = true\n) {\n    const selectionInfo = await psapi.getSelectionInfoExe()\n    //convert the selection box into square box so that you have best output results\n\n    const newSelection = make_square\n        ? makeSquare(selectionInfo, offset)\n        : keepRatio(selectionInfo, offset)\n\n    //correct width and height sliders, since this is lasso mode.\n    await calcWidthHeightFromSelection(newSelection)\n\n    async function getImageFromCanvas() {\n        const width = html_manip.getWidth()\n        const height = html_manip.getHeight()\n\n        const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(\n            width,\n            height,\n            newSelection,\n            true\n        )\n        return base64\n    }\n    const channelToSelection = {\n        _obj: 'set',\n        _target: { _ref: 'channel', _property: 'selection' },\n        to: { _ref: 'channel', _name: channel_name },\n    }\n    // await executeAsModal(async () => {\n    //     const result = await batchPlay(\n    //         [\n    //             ...deleteChannel(channel_name),\n    //             makeMaskChannel(channel_name),\n    //             channelToSelection,\n    //         ],\n    //         { modalBehavior: 'execute', synchronousExecution: true }\n    //     )\n    //     const selection_info = await psapi.getSelectionInfoExe()\n    // })\n    await selectionToChannel(channel_name) //lasso selection to channel called 'mask'\n\n    const init_base64 = await getImageFromCanvas()\n\n    html_manip.setInitImageSrc(general.base64ToBase64Url(init_base64))\n    let mask_base64\n    await executeAsModal(async () => {\n        const result = await batchPlay([channelToSelection], {\n            modalBehavior: 'execute',\n            synchronousExecution: true,\n        })\n        // const selection_info = await psapi.getSelectionInfoExe()\n        mask_base64 = await fillSelectionWhiteOutsideBlack(newSelection)\n    })\n\n    //save laso selection to channel\n    //get laso selection\n    //make rect selection\n    //base64 from selection\n    //and display it in init image html element\n    //get laso selection:\n    //make mask layer\n    //get rectangular selection\n    //get base64 from selection\n    //display it in mask image html element\n    // let jimp_mask = await Jimp.read(Buffer.from(mask_base64, 'base64'))\n    // html_manip.setInitImageMaskSrc(\n    //     await jimp_mask.getBase64Async(Jimp.MIME_PNG)\n    // )\n    html_manip.setInitImageMaskSrc(general.base64ToBase64Url(mask_base64))\n\n    return [init_base64, mask_base64]\n    // //return\n    // //init image\n    //mask\n}\n\nasync function fillSelectionWhiteOutsideBlack(selectionInfo) {\n    // Create a new layer\n    const layer_name = 'mask'\n    const getSelectionDesc = () => ({\n        _obj: 'get',\n        _target: [\n            {\n                _property: 'selection',\n            },\n            {\n                _ref: 'document',\n                _id: app.activeDocument._id,\n            },\n        ],\n        _options: {\n            dialogOptions: 'dontDisplay',\n        },\n    })\n    const invertSelection = () => ({\n        _obj: 'inverse',\n        _isCommand: true,\n    })\n    await psapi.unselectActiveLayers()\n    const mask_layer = await layer_util.createNewLayerExe('mask')\n    await moveToTopLayerStackExe()\n    await batchPlay(\n        [\n            getSelectionDesc(),\n\n            {\n                _obj: 'fill',\n                using: {\n                    _enum: 'fillContents',\n                    _value: 'white',\n                },\n                opacity: {\n                    _unit: 'percentUnit',\n                    _value: 100,\n                },\n                mode: {\n                    _enum: 'blendMode',\n                    _value: 'normal',\n                },\n            },\n            // {\n            //     _obj: 'select',\n            //     _target: [\n            //         {\n            //             _ref: 'channel',\n            //             _property: 'selection',\n            //         },\n            //     ],\n            // },\n            invertSelection(),\n            {\n                _obj: 'fill',\n                using: {\n                    _enum: 'fillContents',\n                    _value: 'black',\n                },\n                opacity: {\n                    _unit: 'percentUnit',\n                    _value: 100,\n                },\n                mode: {\n                    _enum: 'blendMode',\n                    _value: 'normal',\n                },\n            },\n\n            // {\n            //     _obj: 'invert',\n            //     _target: [\n            //         {\n            //             _ref: 'channel',\n            //             _property: 'selection',\n            //         },\n            //     ],\n            // },\n\n            //make new layer\n            // {\n            //     _obj: 'make',\n            //     _target: [\n            //         {\n            //             _ref: 'layer',\n            //         },\n            //     ],\n            //     using: {\n            //         _obj: 'layer',\n            //         name: 'Fill Layer',\n            //     },\n            // },\n\n            {\n                _obj: 'set',\n                _target: [\n                    { _ref: 'layer', _enum: 'ordinal', _value: 'targetEnum' },\n                ],\n                to: { _obj: 'layer', name: layer_name },\n                _options: { dialogOptions: 'dontDisplay' },\n                _isCommand: true,\n            },\n            // getSelectionDesc(),\n            //undo the first inversion of the selection\n            invertSelection(),\n        ],\n        { modalBehavior: 'execute' }\n    )\n\n    await psapi.reSelectMarqueeExe(selectionInfo)\n    const width = html_manip.getWidth()\n    const height = html_manip.getHeight()\n\n    //convert the selection area on the canvas to base64 image\n    const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(\n        width,\n        height,\n        selectionInfo,\n        true,\n        layer_name + '.png'\n    )\n\n    //import the base64 image into the canvas as a new layer\n    // await io.IO.base64ToLayer(\n    //     base64,\n    //     'base64_to_layer_temp.png',\n    //     rect_selection_info.left,\n    //     rect_selection_info.top,\n    //     rect_selection_info.width,\n    //     rect_selection_info.height\n    // )\n\n    await psapi.cleanLayers([mask_layer])\n    return base64\n}\n\nasync function inpaintLasoInitImage() {\n    // Create a new layer\n    const layer_name = 'inpaint_laso_init_image'\n    const getSelectionDesc = () => ({\n        _obj: 'get',\n        _target: [\n            {\n                _property: 'selection',\n            },\n            {\n                _ref: 'document',\n                _id: app.activeDocument._id,\n            },\n        ],\n        _options: {\n            dialogOptions: 'dontDisplay',\n        },\n    })\n    const invertSelection = () => ({\n        _obj: 'inverse',\n        _isCommand: true,\n    })\n    await batchPlay(\n        [\n            getSelectionDesc(),\n\n            {\n                _obj: 'fill',\n                using: {\n                    _enum: 'fillContents',\n                    _value: 'white',\n                },\n                opacity: {\n                    _unit: 'percentUnit',\n                    _value: 100,\n                },\n                mode: {\n                    _enum: 'blendMode',\n                    _value: 'normal',\n                },\n            },\n            // {\n            //     _obj: 'select',\n            //     _target: [\n            //         {\n            //             _ref: 'channel',\n            //             _property: 'selection',\n            //         },\n            //     ],\n            // },\n            invertSelection(),\n            {\n                _obj: 'fill',\n                using: {\n                    _enum: 'fillContents',\n                    _value: 'black',\n                },\n                opacity: {\n                    _unit: 'percentUnit',\n                    _value: 100,\n                },\n                mode: {\n                    _enum: 'blendMode',\n                    _value: 'normal',\n                },\n            },\n\n            // {\n            //     _obj: 'invert',\n            //     _target: [\n            //         {\n            //             _ref: 'channel',\n            //             _property: 'selection',\n            //         },\n            //     ],\n            // },\n\n            //make new layer\n            // {\n            //     _obj: 'make',\n            //     _target: [\n            //         {\n            //             _ref: 'layer',\n            //         },\n            //     ],\n            //     using: {\n            //         _obj: 'layer',\n            //         name: 'Fill Layer',\n            //     },\n            // },\n\n            {\n                _obj: 'set',\n                _target: [\n                    { _ref: 'layer', _enum: 'ordinal', _value: 'targetEnum' },\n                ],\n                to: { _obj: 'layer', name: layer_name },\n                _options: { dialogOptions: 'dontDisplay' },\n                _isCommand: true,\n            },\n            // getSelectionDesc(),\n            //undo the first inversion of the selection\n            invertSelection(),\n        ],\n        { modalBehavior: 'execute' }\n    )\n\n    //get the rectangular bounding box selection\n\n    const rect_selection_info = await psapi.getSelectionInfoExe()\n    await psapi.reSelectMarqueeExe(rect_selection_info)\n    const width = html_manip.getWidth()\n    const height = html_manip.getHeight()\n\n    //convert the selection area on the canvas to base64 image\n    const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(\n        width,\n        height,\n        rect_selection_info,\n        true,\n        layer_name + '.png'\n    )\n\n    //import the base64 image into the canvas as a new layer\n    await io.IO.base64ToLayer(\n        base64,\n        'base64_to_layer_temp.png',\n        rect_selection_info.left,\n        rect_selection_info.top,\n        rect_selection_info.width,\n        rect_selection_info.height\n    )\n    // Fill the current selection with white\n    // await batchPlay(\n    //     [\n    //         {\n    //             _obj: 'fill',\n    //             using: {\n    //                 _enum: 'fillContents',\n    //                 _value: 'white',\n    //             },\n    //             opacity: {\n    //                 _unit: 'percentUnit',\n    //                 _value: 100,\n    //             },\n    //             mode: {\n    //                 _enum: 'blendMode',\n    //                 _value: 'normal',\n    //             },\n    //         },\n    //     ],\n    //     { modalBehavior: 'execute' }\n    // )\n\n    // // Invert the selection\n    // await batchPlay(\n    //     [\n    //         {\n    //             _obj: 'invert',\n    //             _target: [\n    //                 {\n    //                     _ref: 'channel',\n    //                     _property: 'selection',\n    //                 },\n    //             ],\n    //         },\n    //     ],\n    //     { modalBehavior: 'execute' }\n    // )\n\n    // // Fill the inverted selection with black\n    // await batchPlay(\n    //     [\n    //         {\n    //             _obj: 'fill',\n    //             using: {\n    //                 _enum: 'fillContents',\n    //                 _value: 'black',\n    //             },\n    //             opacity: {\n    //                 _unit: 'percentUnit',\n    //                 _value: 100,\n    //             },\n    //             mode: {\n    //                 _enum: 'blendMode',\n    //                 _value: 'normal',\n    //             },\n    //         },\n    //     ],\n    //     { modalBehavior: 'execute' }\n    // )\n}\n\nclass Selection {\n    static async getSelectionInfoExe() {\n        //return a selectionInfo object or undefined\n        try {\n            const selection = await executeAsModal(async () => {\n                const result = await batchPlay([SelectionInfoDesc()], {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                })\n\n                return result[0]?.selection\n            })\n\n            if (this.isSelectionValid(selection)) {\n                let selection_info = {\n                    left: selection.left._value,\n                    right: selection.right._value,\n                    bottom: selection.bottom._value,\n                    top: selection.top._value,\n                    height: selection.bottom._value - selection.top._value,\n                    width: selection.right._value - selection.left._value,\n                }\n                // console.dir({selection_info})\n                return selection_info\n            }\n        } catch (e) {\n            console.warn('selection info error', e)\n        }\n    }\n\n    static isSelectionValid(selection) {\n        console.warn(\n            'isSelectionValid is deprecated use selection.isSelectionValid instead'\n        )\n        if (\n            selection && // check if the selection is defined\n            selection.hasOwnProperty('left') &&\n            selection.hasOwnProperty('right') &&\n            selection.hasOwnProperty('top') &&\n            selection.hasOwnProperty('bottom')\n        ) {\n            return true\n        }\n\n        return false\n    }\n    static reselectArea(selection_info) {}\n    static isSameSelection(selection_info_1, selection_info_2) {}\n    static async getImageToSelectionDifference() {\n        // const selectionInfo = await psapi.getSelectionInfoExe()\n        // const width = html_manip.getWidth()\n        // const height = html_manip.getHeight()\n\n        const selectionInfo = session_store.data.current_selection_info\n        const width = sd_tab_store.data.width\n        const height = sd_tab_store.data.height\n        let ratio =\n            (width * height) / (selectionInfo.width * selectionInfo.height)\n\n        return ratio\n    }\n    static {}\n}\n\nasync function moveToTopLayerStackExe() {\n    const moveToTop = {\n        _obj: 'move',\n        _target: { _ref: 'layer', _enum: 'ordinal', _value: 'targetEnum' },\n        to: { _ref: 'layer', _enum: 'ordinal', _value: 'front' },\n        // _options: { dialogOptions: 'dontDisplay' },\n        options: { failOnMissingProperty: false, failOnMissingElement: false },\n    }\n    try {\n        await executeAsModal(async () => {\n            const layer = app.activeDocument.activeLayers[0]\n\n            while (layer.parent) {\n                console.log(layer.parent)\n                const result = await batchPlay([moveToTop], {\n                    modalBehavior: 'execute',\n                    synchronousExecution: true,\n                })\n            }\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function colorRange() {\n    // const select_current_layer_cmd = {\n    //     _obj: 'set',\n    //     _target: [\n    //         {\n    //             _ref: 'channel',\n    //             _property: 'selection',\n    //         },\n    //     ],\n    //     to: {\n    //         _ref: 'channel',\n    //         _enum: 'channel',\n    //         _value: 'transparencyEnum',\n    //     },\n    //     _isCommand: true,\n    // }\n    const cmd = {\n        _obj: 'colorRange',\n        fuzziness: 0,\n        minimum: {\n            _obj: 'labColor',\n            luminance: 100,\n            a: 0,\n            b: 0,\n        },\n        maximum: {\n            _obj: 'labColor',\n            luminance: 100,\n            a: 0,\n            b: 0,\n        },\n        colorModel: 0,\n        _isCommand: true,\n    }\n    const result = await batchPlay([cmd], {\n        modalBehavior: 'execute',\n        synchronousExecution: true,\n    })\n    return result\n}\n\nasync function colorRangeExe() {\n    let result\n    try {\n        await executeAsModal(\n            async () => {\n                result = await colorRange()\n            },\n            { commandName: 'Convert Black and White Layer to mask selection' }\n        )\n    } catch (e) {\n        console.warn(e)\n    }\n    return result\n}\n\nasync function base64ToLassoSelection(base64, selection_info) {\n    //place the mask on the canvas\n    const mask_layer = await io.IO.base64ToLayer(\n        base64,\n        'monochrome_mask.png',\n        selection_info.left,\n        selection_info.top,\n        selection_info.width,\n        selection_info.height\n    )\n    //reselect the selection area\n    await psapi.reSelectMarqueeExe(selection_info)\n    //reselect the layer\n    await psapi.selectLayersExe([mask_layer])\n    await executeAsModal(async () => {\n        await layer_util.toggleActiveLayer() // undo the toggling operation, active layer will be visible\n        //select the white pixels\n        await colorRange()\n    })\n    // await colorRangeExe()\n    //delete the mask layer. we only needed to select the white pixels\n    await executeAsModal(async () => {\n        await layer_util.toggleActiveLayer() // undo the toggling operation, active layer will be visible\n    })\n    await layer_util.deleteLayers([mask_layer])\n}\n\nasync function base64ToChannel(base64, selection_info, channel_name) {\n    try {\n        await executeAsModal(async (context) => {\n            const history_id = await context.hostControl.suspendHistory({\n                documentID: app.activeDocument.id, //TODO: change this to the session document id\n                name: 'Mask Image',\n            })\n\n            const layer = app.activeDocument.activeLayers[0]\n\n            if (!layer_util.Layer.doesLayerExist(layer)) {\n                return null\n            }\n            await psapi.unSelectMarqueeExe()\n            await psapi.unselectActiveLayersExe()\n            await base64ToLassoSelection(base64, selection_info)\n\n            const expand_cmd = {\n                _obj: 'expand',\n                by: {\n                    _unit: 'pixelsUnit',\n                    _value: 10,\n                },\n                selectionModifyEffectAtCanvasBounds: true,\n                _isCommand: true,\n            }\n            const channelToSelection = {\n                _obj: 'set',\n                _target: { _ref: 'channel', _property: 'selection' },\n                to: { _ref: 'channel', _name: channel_name },\n            }\n            await executeAsModal(async () => {\n                const result = await batchPlay(\n                    [\n                        expand_cmd,\n                        ...deleteChannel(channel_name),\n                        makeMaskChannel(channel_name),\n                        channelToSelection,\n                    ],\n                    { modalBehavior: 'execute', synchronousExecution: true }\n                )\n            })\n            await psapi.selectLayersExe([layer])\n            await applyMaskChannelExe(channel_name)\n\n            // context = stored_context\n            await context.hostControl.resumeHistory(history_id)\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function black_white_layer_to_mask(mask_id, target_layer_id, mask_name) {\n    let result\n    let psAction = require('photoshop').action\n\n    let command = [\n        //\n        ...deleteChannel(mask_name),\n        // Select layer “Layer 33”\n        {\n            _obj: 'select',\n            _target: [{ _id: mask_id, _ref: 'layer' }],\n            // layerID: [3862],\n            makeVisible: false,\n        },\n        // Set Selection\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: {\n                _enum: 'channel',\n                _ref: 'channel',\n                _value: 'transparencyEnum',\n            },\n        },\n        // Color Range\n        {\n            _obj: 'colorRange',\n            colorModel: 0,\n            fuzziness: 0,\n            maximum: { _obj: 'labColor', a: 0.0, b: 0.0, luminance: 100.0 },\n            minimum: { _obj: 'labColor', a: 0.0, b: 0.0, luminance: 100.0 },\n        },\n        // Duplicate Selection, make sure you delete the any mask that share the same name\n        {\n            _obj: 'duplicate',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            name: mask_name,\n        },\n        // Select channel “Alpha 1”\n        { _obj: 'select', _target: [{ _name: mask_name, _ref: 'channel' }] },\n        // Set Selection\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },\n        },\n        // Select layer “Layer 43”\n        {\n            _obj: 'select',\n            _target: [{ _id: target_layer_id, _ref: 'layer' }],\n            // layerID: [3879],\n            makeVisible: false,\n        },\n        // Make\n        {\n            _obj: 'make',\n            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },\n            new: { _class: 'channel' },\n            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },\n        },\n    ]\n    result = await psAction.batchPlay(command, {})\n}\n\nasync function black_white_layer_to_mask_multi_batchplay(\n    mask_id,\n    target_layer_id,\n    mask_name,\n    expand_by = 10\n) {\n    let result\n    let psAction = require('photoshop').action\n    const timer = (ms) => new Promise((res) => setTimeout(res, ms))\n\n    let command1 = [\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: { _enum: 'ordinal', _value: 'none' },\n        },\n        //\n        ...deleteChannel(mask_name),\n        // Select layer “Layer 33”\n        {\n            _obj: 'select',\n            _target: [{ _id: mask_id, _ref: 'layer' }],\n            // layerID: [3862],\n            makeVisible: false,\n        },\n        // Set Selection\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: {\n                _enum: 'channel',\n                _ref: 'channel',\n                _value: 'transparencyEnum',\n            },\n        },\n    ]\n    let command2 = [\n        // Color Range\n        {\n            _obj: 'colorRange',\n            colorModel: 0,\n            fuzziness: 0,\n            maximum: { _obj: 'labColor', a: 0.0, b: 0.0, luminance: 100.0 },\n            minimum: { _obj: 'labColor', a: 0.0, b: 0.0, luminance: 100.0 },\n        },\n        {\n            _obj: 'expand',\n            by: {\n                _unit: 'pixelsUnit',\n                _value: expand_by,\n            },\n            selectionModifyEffectAtCanvasBounds: true,\n            _isCommand: true,\n        },\n    ]\n    let command3 = [\n        // Duplicate Selection, make sure you delete the any mask that share the same name\n        {\n            _obj: 'duplicate',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            name: mask_name,\n        },\n        // Select channel “Alpha 1”\n        {\n            _obj: 'select',\n            _target: [{ _name: mask_name, _ref: 'channel' }],\n        },\n        // Set Selection\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },\n        },\n        // Select layer “Layer 43”\n        {\n            _obj: 'select',\n            _target: [{ _id: target_layer_id, _ref: 'layer' }],\n            // layerID: [3879],\n            makeVisible: false,\n        },\n        // Make\n        {\n            _obj: 'make',\n            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },\n            new: { _class: 'channel' },\n            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },\n        },\n    ]\n    await timer(g_timer_value)\n    // result = await psAction.batchPlay(command, {})\n\n    await executeAsModal(async () => {\n        result = await psAction.batchPlay(command1, {})\n    })\n\n    await timer(g_timer_value)\n    await executeAsModal(async () => {\n        await layer_util.toggleActiveLayer() // toggle active layer will be visible, note: doesn't solve the issue in outpaint mode\n        result = await psAction.batchPlay(command2, {})\n    })\n\n    await timer(g_timer_value)\n    await executeAsModal(async () => {\n        await layer_util.toggleActiveLayer() // undo the toggling operation, active layer will be visible, note: doesn't solve the issue in outpaint mode\n        result = await psAction.batchPlay(command3, {})\n    })\n}\n\nmodule.exports = {\n    finalWidthHeight,\n    selectionToFinalWidthHeight,\n    selectBoundingBox,\n    convertSelectionObjectToSelectionInfo,\n    Selection,\n\n    makeMaskChannel,\n    makeMaskChannelExe,\n    fillSelectionWhiteOutsideBlack,\n    inpaintLasoInitImage,\n    applyMaskChannelExe,\n    createLayerFromMaskChannel,\n    multiGetExe,\n    inpaintLassoInitImageAndMask,\n    channelToSelectionExe,\n    moveToTopLayerStackExe,\n    colorRangeExe,\n    base64ToLassoSelection,\n    base64ToChannel,\n    deleteChannel,\n    selectionToChannel,\n    black_white_layer_to_mask,\n    black_white_layer_to_mask_multi_batchplay,\n}\n"
  },
  {
    "path": "server/python_server/global_state.py",
    "content": "#code copied from controlnet repo global_state.py  \n\n\npreprocessor_filters = {\n    \"All\": \"none\",\n    \"Canny\": \"canny\",\n    \"Depth\": \"depth_midas\",\n    \"Normal\": \"normal_bae\",\n    \"OpenPose\": \"openpose_full\",\n    \"MLSD\": \"mlsd\",\n    \"Lineart\": \"lineart_standard (from white bg & black line)\",\n    \"SoftEdge\": \"softedge_pidinet\",\n    \"Scribble\": \"scribble_pidinet\",\n    \"Seg\": \"seg_ofade20k\",\n    \"Shuffle\": \"shuffle\",\n    \"Tile\": \"tile_resample\",\n    \"Inpaint\": \"inpaint_only\",\n    \"IP2P\": \"none\",\n    \"Reference\": \"reference_only\",\n    \"T2IA\": \"none\",\n}\n\ncn_preprocessor_modules = [\"none\",\n    \"canny\",\n    \"depth\",\n    \"depth_leres\",\n    \"depth_leres++\",\n    \"hed\",\n    \"hed_safe\",\n    \"mediapipe_face\",\n    \"mlsd\",\n    \"normal_map\",\n    \"openpose\",\n    \"openpose_hand\",\n    \"openpose_face\",\n    \"openpose_faceonly\",\n    \"openpose_full\",\n    \"clip_vision\",\n    \"color\",\n    \"pidinet\",\n    \"pidinet_safe\",\n    \"pidinet_sketch\",\n    \"pidinet_scribble\",\n    \"scribble_xdog\",\n    \"scribble_hed\",\n    \"segmentation\",\n    \"threshold\",\n    \"depth_zoe\",\n    \"normal_bae\",\n    \"oneformer_coco\",\n    \"oneformer_ade20k\",\n    \"lineart\",\n    \"lineart_coarse\",\n    \"lineart_anime\",\n    \"lineart_standard\",\n    \"shuffle\",\n    \"tile_resample\",\n    \"invert\",\n    \"lineart_anime_denoise\",\n    \"reference_only\",\n    \"reference_adain\",\n    \"reference_adain+attn\",\n    \"inpaint\",\n    \"inpaint_only\",\n    \"inpaint_only+lama\",\n    \"tile_colorfix\",\n    \"tile_colorfix+sharp\",\n]\n\npreprocessor_aliases = {\n    \"invert\": \"invert (from white bg & black line)\",\n    \"lineart_standard\": \"lineart_standard (from white bg & black line)\",\n    \"lineart\": \"lineart_realistic\",\n    \"color\": \"t2ia_color_grid\",\n    \"clip_vision\": \"t2ia_style_clipvision\",\n    \"pidinet_sketch\": \"t2ia_sketch_pidi\",\n    \"depth\": \"depth_midas\",\n    \"normal_map\": \"normal_midas\",\n    \"hed\": \"softedge_hed\",\n    \"hed_safe\": \"softedge_hedsafe\",\n    \"pidinet\": \"softedge_pidinet\",\n    \"pidinet_safe\": \"softedge_pidisafe\",\n    \"segmentation\": \"seg_ufade20k\",\n    \"oneformer_coco\": \"seg_ofcoco\",\n    \"oneformer_ade20k\": \"seg_ofade20k\",\n    \"pidinet_scribble\": \"scribble_pidinet\",\n    \"inpaint\": \"inpaint_global_harmonious\",\n}\n\ndef filter_selected_helper(k,preprocessor_list,model_list):\n    if 'None' not in model_list:\n        model_list = ['None'] + model_list\n    ui_preprocessor_keys = ['none', preprocessor_aliases['invert']]\n\n  \n    ui_preprocessor_keys += sorted([preprocessor_aliases.get(k, k)\n                                    for k in preprocessor_list\n                                    if preprocessor_aliases.get(k, k) not in ui_preprocessor_keys])\n    \n\n    preprocessor_list = ui_preprocessor_keys\n    # print(\"preprocessor_list sorted: \",preprocessor_list)\n    model_list = list(model_list)\n    # print(\"list(model_list): \",model_list)\n\n    # print(\"k:\",k,k.lower())\n    \n\n    default_option = preprocessor_filters[k]\n    pattern = k.lower()\n    # model_list = list(cn_models.keys())\n    if pattern == \"all\":\n        return [\n            preprocessor_list,\n            model_list,\n            'none', #default option\n            \"None\"  #default model \n            ] \n    filtered_preprocessor_list = [\n        x\n        for x in preprocessor_list\n        if pattern in x.lower() or x.lower() == \"none\"\n    ]\n    if pattern in [\"canny\", \"lineart\", \"scribble\", \"mlsd\"]:\n        filtered_preprocessor_list += [\n            x for x in preprocessor_list if \"invert\" in x.lower()\n        ]\n\n    ##Debug start\n    # for model in model_list:\n    #     print(\"model: \",model)\n    #     if pattern in model.lower():\n    #         print('add to filtered')\n    #         print(\"pattern:\",pattern, \"in model.lower():\",model.lower())\n    #     else:\n    #         print(\"pattern:\",pattern, \"not in model.lower():\",model.lower())\n    ##Debug end\n    \n    filtered_model_list = [\n        x for x in model_list if pattern in x.lower() or x.lower() == \"none\"\n    ]\n    if default_option not in filtered_preprocessor_list:\n        default_option = filtered_preprocessor_list[0]\n    if len(filtered_model_list) == 1:\n        default_model = \"None\"\n        filtered_model_list = model_list\n    else:\n        default_model = filtered_model_list[1]\n        for x in filtered_model_list:\n            if \"11\" in x.split(\"[\")[0]:\n                default_model = x\n                break\n    \n    return [filtered_preprocessor_list,filtered_model_list, default_option,default_model]\n"
  },
  {
    "path": "server/python_server/img2imgapi.py",
    "content": "import json\nimport requests\nimport io\nimport base64\nfrom PIL import Image, PngImagePlugin\n# from serverMain import sd_url\nimport asyncio\nimport httpx\n\n\nfrom io import BytesIO\nimport prompt_shortcut\n\n# Convert Image to Base64 \ndef img_2_b64(image):\n    buff = BytesIO()\n    image.save(buff, format=\"PNG\")\n    img_byte = base64.b64encode(buff.getvalue())\n    img_str = img_byte.decode(\"utf-8\")\n    return img_str\n\nimport time\nimport serverHelper\nimport metadata_to_json\n\ndef b64_2_img(base64_image):\n     image = Image.open(io.BytesIO(base64.b64decode(base64_image.split(\",\",1)[0])))\n     return image\n\ndef reserveBorderPixels(img,dilation_img):\n    pixels = img.load() # this is not a list, nor is it list()'able\n    width, height = img.size\n    dilation_pixels =  dilation_img.load()\n    all_pixels = []\n    depth = 1 # five pixel depth\n    for x in range(width):\n        for d in range(depth): \n            dilation_pixels[x,d] =  pixels[x, d]\n            dilation_pixels[x,height-(d+1)] =  pixels[x, height-(d+1)]\n        # all_pixels.append(cpixel)\n    for y in range(height):\n        for d in range(depth): \n            dilation_pixels[d,y] =  pixels[d,y] # d = 0\n            dilation_pixels[width-(d+1),y] =  pixels[width-(d+1), y]\n    return dilation_img\n        \ndef maskExpansion(mask_img,mask_expansion,blur =10):\n     #only if image exist then try to open it\n    \n        \n        # init_img_mask = Image.open(f\"{init_img_dir}/{init_img_mask_name}\")\n        \n        # if(payload['use_sharp_mask'] == False):# use blurry mask \n        iteration = mask_expansion\n        dilated_img = applyDilation(mask_img,iteration)\n        blurred_image = dilated_img.filter(ImageFilter.GaussianBlur(radius = blur))\n        mask_with_border = reserveBorderPixels(mask_img,blurred_image)\n        return mask_with_border\n        \nasync def base64ToPng(base64_image,image_path):\n    base64_img_bytes = base64_image.encode('utf-8')\n    with open(image_path, 'wb') as file_to_save:\n        decoded_image_data = base64.decodebytes(base64_img_bytes)\n        file_to_save.write(decoded_image_data)    \n        \n        \n\n\nfrom PIL import Image, ImageFilter\ndef applyDilation(img,iteration=20,max_filter=3):\n    # img = Image.open(\"test_image_2.png\")\n    dilation_img = img.copy()\n    # for i in range(20):\n    #     dilation_img = dilation_img.filter(ImageFilter.MaxFilter(3))\n    for i in range(iteration):\n        dilation_img = dilation_img.filter(ImageFilter.MaxFilter(max_filter))\n    return dilation_img\n\n\n\nasync def img2ImgRequest(sd_url,payload):\n    # init_img = Image.open(r\"C:/Users/abdul/Desktop/photoshop_plugins/my_plugin_1/server/python_server/output- 1670544300.95411.png\") \n    print(\"payload debug:\",payload)\n    \n    if(payload['use_prompt_shortcut']): # use edit prompt\n        #edit prompt, replaceShortcut(prompt)\n        prompt_shortcut_dict = prompt_shortcut.load()\n        prompt_shortcut_dict.update(payload[\"prompt_shortcut_ui_dict\"])\n        payload['prompt'] = prompt_shortcut.replaceShortcut(payload['prompt'],prompt_shortcut_dict)\n        # edit negative prompt, replaceShortcut(negative_prompt)\n        payload['negative_prompt'] = prompt_shortcut.replaceShortcut(payload['negative_prompt'],prompt_shortcut_dict)\n        \n    init_img_dir = \"./init_images\"\n    init_img_name = payload['init_image_name']\n    init_img = Image.open(f\"{init_img_dir}/{init_img_name}\")\n    init_img_str = img_2_b64(init_img) \n    payload['init_images'] = [init_img_str]\n\n    # mask\n\n    init_img_mask_name = payload.get('init_image_mask_name',\"\")\n    \n\n    #only if image exist then try to open it\n    if(len(init_img_mask_name) > 0):\n        init_img_mask = Image.open(f\"{init_img_dir}/{init_img_mask_name}\")\n        \n        if(payload['use_sharp_mask'] == False):# use blurry mask \n            iteration = payload['mask_expansion']\n            init_img_mask = applyDilation(init_img_mask,iteration)\n\n        init_img_mask_str = img_2_b64(init_img_mask) \n        payload['mask'] = init_img_mask_str #there is only one mask, unlike 'init_images' which is of type array\n\n\n    # payload = { \n    #     \"prompt\": \"cute dog\",\n    #     \"steps\": 10,\n    #     \"init_images\":[init_img_str],\n    #     \"n_iter\":3\n    # }\n    # print(\"payload:\",payload)\n    print(type(init_img_str))\n    #request the images to be generated\n    async with httpx.AsyncClient() as client:\n        response = await client.post(url=f'{sd_url}/sdapi/v1/img2img', json=payload, timeout=None)\n\n        r = response.json()\n\n        #create a directory to store the images at\n        # dirName = f'{time.time()}'\n        # dir_fullpath,dirName = serverHelper.makeDirPathName()\n        uniqueDocumentId = payload['uniqueDocumentId']\n        dir_fullpath,dirName = serverHelper.getUniqueDocumentDirPathName(uniqueDocumentId)\n        serverHelper.createFolder(dir_fullpath)\n        image_paths = []\n        metadata = []\n        images_info = []\n        #for each image store the prompt and settings in the meta data\n        for i in r['images']:\n            image = Image.open(io.BytesIO(base64.b64decode(i.split(\",\",1)[0])))\n\n            png_payload = {\n                \"image\": \"data:image/png;base64,\" + i\n            }\n            response2 = await client.post(url=f'{sd_url}/sdapi/v1/png-info', json=png_payload, timeout=None)\n            pnginfo = PngImagePlugin.PngInfo()\n            pnginfo.add_text(\"parameters\", response2.json().get(\"info\"))\n            image_name = f'output- {time.time()}.png'\n            image_path = f'output/{dirName}/{image_name}'\n            image_paths.append(image_path)\n            image.save(f'./{image_path}', pnginfo=pnginfo)\n\n            metadata_info = response2.json().get(\"info\")\n            metadata_json = metadata_to_json.convertMetadataToJson(metadata_info)\n            metadata.append(metadata_json)\n            images_info.append({\"base64\":i,\"path\":image_path})\n            print(\"metadata_json: \", metadata_json)   \n        \n        return dirName,images_info,metadata\n\nif __name__==\"__main__\":\n    img2ImgRequest()"
  },
  {
    "path": "server/python_server/init_images/.gitignore",
    "content": "# Ignore everything in this directory\n*\n# Except this file\n!.gitignore"
  },
  {
    "path": "server/python_server/metadata_to_json.py",
    "content": "import os\nfrom pathlib import Path\nfrom PIL import Image\nimport json\n\nimport serverHelper\n# metadata_str = 'cute cat\\nSteps: 20, Sampler: Euler a, CFG scale: 7.0, Seed: 2253354038, Size: 512x512, Model hash: 3e16efc8, Seed resize from: -1x-1, Denoising strength: 0, Conditional mask weight: 1.0'\ndef convertMetadataToJson(metadata_str):\n    print(metadata_str)\n    last_new_line_index = metadata_str.rindex('\\n')\n    prompt = metadata_str[:last_new_line_index]\n    other_settings = metadata_str[last_new_line_index+1:] \n\n    print(\"prompt:\", prompt)\n    print(\"other_settings:\", other_settings)\n    sub_settings = other_settings.split(\",\")\n    print(\"sub_settings: \",sub_settings)\n\n    settings_dict = {}\n    settings_dict['prompt'] = prompt\n\n    for setting in sub_settings:\n        [key,value]= setting.split(\":\")\n        key =  key.lstrip(' ')\n        value =  value.lstrip(' ')\n        settings_dict[key] = value\n    import json\n    settings_json = json.dumps(settings_dict)\n    print(\"settings_dict: \",settings_dict)\n    print(\"settings_json \",settings_json)\n    return settings_json\n\n\n\n\ndef getMetadataFromPng(image_path):\n    # image_path = \"./output/5c42fd2a-6708-45e2-b282-2e9f3894368e/output- 1672476035.4888158.png\"\n    # image_path = \"C:/Users/abdul/Desktop/auto-photoshop/Auto-Photoshop-StableDiffusion-Plugin/server/python_server/output/5c42fd2a-6708-45e2-b282-2e9f3894368e/output- 1672476035.4888158.png\"\n    im = Image.open(image_path) \n    # im.load()  # Needed only for .png EXIF data (see citation above)\n    # print(im.info['parameters'])\n    metadata_string = im.info['parameters']\n    metadata_json_string = convertMetadataToJson(metadata_string)\n    metadata_dict = json.loads(metadata_json_string)\n    print(\"metadata_dict: \", metadata_dict)\n    # print(im.info['meta_to_read'])\n    return metadata_dict\n\n\ndef createMetadataJsonFileIfNotExist(image_path):\n    \n    # image_name = os.path.splitext(image_path)\n    image_name = Path(image_path).stem\n    # parent_dir_path = Path(image_path)\n    # parent_dir_path = image_path.split(image_name)[0]\n    # os.path.join()\n    head = os.path.split(image_path)[0]\n    json_file_tail = f'{image_name}.json'\n    json_full_path = os.path.join(head,json_file_tail)\n    print(\"image_name: \",image_name)\n    print(\"json_full_path: \",json_full_path)\n    isExist = os.path.exists(json_full_path)\n    if(isExist):\n        #read metadata from json\n        metadata_dict = serverHelper.readJson(json_full_path)\n        \n    else:\n        #read metadata from image\n        #save the metadata to a json file\n        metadata_dict = getMetadataFromPng(image_path)\n        serverHelper.writeJson(json_full_path,metadata_dict)\n    return metadata_dict\n        \n\nif __name__ == \"__main__\":\n    image_path = \"C:/Users/abdul/Desktop/auto-photoshop/Auto-Photoshop-StableDiffusion-Plugin/server/python_server/output/5c42fd2a-6708-45e2-b282-2e9f3894368e/output- 1672476035.4888158.png\"\n    # getMetadataFromPng(image_path)\n    createMetadataJsonFileIfNotExist(image_path)\n"
  },
  {
    "path": "server/python_server/output/.gitignore",
    "content": "# Ignore everything in this directory\n*\n# Except this file\n!.gitignore"
  },
  {
    "path": "server/python_server/prompt_shortcut - Copy.json",
    "content": "{\n    \"painterly_style_1\": \"A full portrait of a beautiful post apocalyptic offworld arctic explorer, intricate, elegant, highly detailed, digital painting, artstation, concept art, smooth, sharp focus, illustration\",\n    \"ugly\": \" ((((ugly)))), (((duplicate))), ((morbid)), ((mutilated)), out of frame, extra fingers, mutated hands, ((poorly drawn hands)), ((poorly drawn face)), (((mutation))), (((deformed))), ((ugly)), blurry, ((bad anatomy)), (((bad proportions))), ((extra limbs)), cloned face, (((disfigured))), out of frame, ugly, extra limbs, (bad anatomy), gross proportions, (malformed limbs), ((missing arms)), ((missing legs)), (((extra arms))), (((extra legs))), mutated hands, (fused fingers), (too many fingers), (((long neck)))\",\n    \"art_style\": \"(SPACE1999:1.0),(dreamlikeart style:1.0), ( redshift style:1.0), (analog style:1.2), (studio_ghibli_anime_style style:0.7), (copeseethemald style:0.8)\",\n    \"woman_style\": \"woman, 1girls, solo, detailed face, lips, realistic pupils, closeup, centered,  standing, centered, skin pores, subsurface scattering, detailed skin\",\n    \"environment_style\": \"detailed background, items, realistic proportions, blushing, masterpiece, best quality, realistic, hyperrealistic, sharp focus, absurdres, good anatomy\",\n    \"uniform_style\": \"space uniform, red, smooth, black belt, black boots\",\n    \"man_style\": \"man, solo, detailed face, lips, realistic pupils, closeup, centered,  standing, centered, skin pores, subsurface scattering, detailed skin\",\n    \"neg_person\": \"(glossy:1.0), freckles, nipples, small waist, lowres, large head, long neck, blurry, bad anatomy, bad hands, extra limbs, extra hands, mutated hands, mutated fingers, missing hand, missing finger, text, error, missing fingers, extra digit, fewer digits,\",\n    \"neg_general\": \"cropped, worst quality, low quality, normal quality, jpeg artifacts, text, signature, watermark, artist name, logo,\",\n    \"nova_green\": \"[Julianne Hough:Jaime King:0.5]\"\n}"
  },
  {
    "path": "server/python_server/prompt_shortcut.py",
    "content": "import re\nimport json\nprompt_shortcut_dict ={}\n\n\ndef readToJson():\n    return load()\n\ndef writeToJson(file_name,data_dict):\n    with open(file_name, \"w\") as outfile:\n        json.dump(data_dict, outfile,indent=4)\n\n\ndef load(): \n    global prompt_shortcut_dict\n    try:\n        with open('prompt_shortcut.json') as f_obj:\n            data = json.load(f_obj)\n            prompt_shortcut_dict = data\n            print(data)\n    except IOError:\n        print(\"prompt_shortcut.json is not found\")\n    return prompt_shortcut_dict\ndef find_words_inside_braces(string):\n    result = \"\"\n    pattern =\"\\{(.*?)\\}\"\n    keywords = []\n    for match in re.findall(pattern, string):\n        keywords.append(match)\n        result += match\n    return keywords\n\n# text = \"a beautiful girl holding a cute cat {style_1} on sunny day\"\n# text = \"a beautiful girl holding a cute cat {    style_1 } on sunny day\"\ntext = \"a beautiful girl{    }, {char1}, {painterly_style} holding a cute cat {    style_1 } on sunny day\"\n# text = \"a beautiful girl {char1 } holding a cute cat on sunny day\"\n\n\n\ndef replaceShortcut(text,prompt_shortcut_dict):\n    raw_keywords = find_words_inside_braces(text)\n    strip_keywords = list(map(lambda s: s.strip(),raw_keywords))\n\n    original_substrings = list(map(lambda s: '{'+s+'}',raw_keywords)) \n\n    print(\"raw_keywords: \", raw_keywords)\n    print(\"strip_keywords: \", strip_keywords)\n    print(\"original_substrings: \",original_substrings)\n    # print (\"text:\",text)\n\n    for i, word in enumerate(strip_keywords):\n        # word = word.strip()\n        print(\"word: \",word)\n        if len(word) > 0 and word in prompt_shortcut_dict:\n            prompt = prompt_shortcut_dict[word]\n            print(\"prompt: \",prompt)\n            text = text.replace(original_substrings[i],prompt)\n        # else:\n            # text = text.replace(word,word.strip())\n    print (\"final text: \",text) \n    return text"
  },
  {
    "path": "server/python_server/search.py",
    "content": "import asyncio\n\ntry:\n    from duckduckgo_search import AsyncDDGS\nexcept ImportError:\n    raise ImportError(\n        \"duckduckgo_search is required to image search. Please install it with `pip install --upgrade duckduckgo_search`.\"\n    )\n\n\nasync def imageSearch(keywords=\"cute cats\"):\n    async with AsyncDDGS() as ddgs:\n        return [\n            x async for x in ddgs.images(keywords, safesearch=\"off\", max_results=50)\n        ]\n\n\nasync def main():\n    result = await imageSearch()\n    print(\"result: \", result)\n    # result = await imageSearch2()\n    # print(result)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n"
  },
  {
    "path": "server/python_server/serverHelper.py",
    "content": "import time\nimport os\nimport datetime\nimport uuid\nimport json\n\n# this function should be used whenever we need to write to json file\ndef writeJson(file_name,data_dict):\n    with open(file_name, 'w', encoding='utf-8') as outfile:\n        json.dump(data_dict, outfile, ensure_ascii=False, indent=4)\n        \n    \n    \n\n# this function should be used whenever we need to read from json file\ndef readJson(file_name): \n    data_dict = {}\n    try:\n        with open(file_name) as f_obj:\n            data_dict = json.load(f_obj)\n            \n            print(\"readJson: data_dict: \", data_dict)\n    except IOError:\n        print(f\"{file_name} is not found\")\n    return data_dict\n\ndef createFolder(fullpath):\n    print(\"fullpath:\",fullpath)\n    \n    if not os.path.exists(fullpath):\n        os.mkdir(fullpath)\n#create string dir path name based on the current time\ndef makeDirPathName():\n    # dirName = f'{time.time()}'\n    currentDirPath = os.getcwd()\n    now = datetime.datetime.now()\n    daily_folder = now.strftime(\"%Y-%m-%d\")\n    output_path = os.path.join(currentDirPath,\"output\")\n    fullpath = os.path.join(output_path,daily_folder)\n    # fullpath = os.path.join(currentDirPath,dirName)\n    return fullpath,daily_folder\n\n#create string dir path name based on the uniqueDocumentId\ndef getUniqueDocumentDirPathName(uniqueDocumentId):\n    \n    currentDirPath = os.getcwd()\n    output_path = os.path.join(currentDirPath,\"output\")\n    fullpath = os.path.join(output_path,uniqueDocumentId)\n\n    return fullpath,uniqueDocumentId\n\ndef makeUniqueID():\n    myuuid = uuid.uuid4()\n    print('Your UUID is: ' + str(myuuid))\n    return myuuid\n\n\nif __name__ == \"__main__\":\n    # currentDirPath = os.getcwd()\n    # dirName = f'{time.time()}'\n    # fullpath = os.path.join(currentDirPath,dirName)\n    # createFolder(fullpath)\n    id = makeUniqueID()\n    print(\"id: \",id)"
  },
  {
    "path": "server/python_server/serverMain.py",
    "content": "\nimport json\nimport requests\nimport io\nimport base64\nfrom PIL import Image, PngImagePlugin\nimport asyncio\nimport httpx\nfrom typing import List\n\nimport os\nimport time\nimport serverHelper\nimport prompt_shortcut\nimport metadata_to_json\nimport search\nimport global_state\n\nsd_url = os.environ.get('SD_URL', 'http://127.0.0.1:7860')\n\n\n\n\nasync def txt2ImgRequest(payload):\n    # payload = { \n    #     \"prompt\": \"cute cat, kitten\",\n    #     \"steps\": 10\n    # }\n    print(\"payload: \",payload)\n    \n    if(payload['use_prompt_shortcut']): # use edit prompt\n        #edit prompt, replaceShortcut(prompt)\n        prompt_shortcut_dict = prompt_shortcut.load()\n        prompt_shortcut_dict.update(payload[\"prompt_shortcut_ui_dict\"])\n        payload['prompt'] = prompt_shortcut.replaceShortcut(payload['prompt'],prompt_shortcut_dict)\n        # edit negative prompt, replaceShortcut(negative_prompt)\n        payload['negative_prompt'] = prompt_shortcut.replaceShortcut(payload['negative_prompt'],prompt_shortcut_dict)\n        \n    \n    #request the images to be generated\n    request_path = \"/sdapi/v1/txt2img\"\n    \n    async with httpx.AsyncClient() as client:\n        response = await client.post(url=f'{sd_url}/sdapi/v1/txt2img', json=payload, timeout=None)\n        r = response.json()\n\n        #create a directory to store the images at\n        # dirName = f'{time.time()}'\n        # dir_fullpath,dirName = serverHelper.makeDirPathName()\n        uniqueDocumentId = payload['uniqueDocumentId']\n        dir_fullpath,dirName = serverHelper.getUniqueDocumentDirPathName(uniqueDocumentId)\n        serverHelper.createFolder(dir_fullpath)\n        image_paths = []\n        #for each image store the prompt and settings in the meta data\n        metadata = []\n        images_info = []\n        for i in r['images']:\n            image = Image.open(io.BytesIO(base64.b64decode(i.split(\",\",1)[0])))\n\n            png_payload = {\n                \"image\": \"data:image/png;base64,\" + i\n            }\n            response2 = await client.post(url=f'{sd_url}/sdapi/v1/png-info', json=png_payload)\n            pnginfo = PngImagePlugin.PngInfo()\n            pnginfo.add_text(\"parameters\", response2.json().get(\"info\"))\n            image_name = f'output- {time.time()}.png'\n            \n            image_path = f'output/{dirName}/{image_name}'\n            image_paths.append(image_path)\n            image.save(f'./{image_path}', pnginfo=pnginfo)\n            \n            metadata_info = response2.json().get(\"info\")\n            metadata_json = metadata_to_json.convertMetadataToJson(metadata_info)\n            metadata.append(metadata_json)\n            images_info.append({\"base64\":i,\"path\":image_path})\n            print(\"metadata_json: \", metadata_json)\n        \n        \n        return dirName,images_info,metadata\n\nimport base64\nfrom io import BytesIO\n\n\ndef img_2_b64(image):\n    buff = BytesIO()\n    image.save(buff, format=\"PNG\")\n    img_byte = base64.b64encode(buff.getvalue())\n    img_str = img_byte.decode(\"utf-8\")\n    return img_str\n\n\nfrom typing import Union\n\n\nfrom fastapi import FastAPI,APIRouter, Request,Query, Body\n\n\n\nrouter = APIRouter()\n\n\n@router.get(\"/\")\ndef read_root():\n    return {\"Hello\": \"World\"}\n\n\n@router.get(\"/version\")\ndef getVersion():\n    manifest_dir = \"..\\..\\manifest.json\"\n    \n    manifest = {'version': '0.0.0'}\n    version = \"0.0.0\"\n    try:\n\n        with open(manifest_dir, 'r') as f:\n            manifest = json.load(f)\n            version = manifest['version']\n    except:\n        print(\"couldn't read the manifest.json\")\n    return {\"version\": f\"v{version}\"}\n\n\n\n\n\n\n# @router.post(\"/txt2img/\")\n# async def txt2ImgHandle(payload:Payload):\n#     print(\"txt2ImgHandle: \\n\")\n#     txt2ImgRequest(payload)\n#     return {\"prompt\":payload.prompt,\"images\": \"\"}\n\n\nfrom fastapi import Request, Response\nimport img2imgapi\n\n\n\n\n\n\n@router.post(\"/sd_url/\")\nasync def changeSdUrl(request:Request):\n    global sd_url\n    try:\n\n        payload = await request.json()\n        print(\"changeSdUrl: payload:\",payload)\n        print(f\"change sd url from {sd_url} to {payload['sd_url']} \\n\")\n        sd_url = payload['sd_url']\n    except:\n        print(\"error occurred in changeSdUrl()\")\n        #  response.body = resp.content\n        # return {}\n    return {\"sd_url\":sd_url}\n\n\n\n\n\n\n\n\n\n@router.post(\"/txt2img/\")\nasync def txt2ImgHandle(request:Request):\n    print(\"txt2ImgHandle: \\n\")\n    payload = await request.json() \n    dir_name,images_info,metadata, = await txt2ImgRequest(payload)\n    # return {\"prompt\":payload.prompt,\"images\": \"\"}\n    return {\"payload\": payload,\"dir_name\": dir_name,\"images_info\":images_info,\"metadata\":metadata}\n\n@router.post(\"/img2img/\")\nasync def img2ImgHandle(request:Request):\n    print(\"img2ImgHandle: \\n\")\n    payload = await request.json() \n    dir_name,images_info,metadata = await img2imgapi.img2ImgRequest(sd_url,payload)\n    # return {\"prompt\":payload.prompt,\"images\": \"\"}\n    return {\"payload\": payload,\"dir_name\": dir_name,\"images_info\":images_info,\"metadata\":metadata}\n\n\n\n\n\n\n@router.post(\"/getInitImage/\")\nasync def getInitImageHandle(request:Request):\n    print(\"getInitImageHandle: \\n\")\n    payload = await request.json() \n    print(\"payload:\",payload)\n    init_img_dir = \"./init_images\"\n    init_img_name = payload[\"init_image_name\"]# change this to \"image_name\"\n    \n    numOfAttempts = 3\n    init_img_str = \"\"\n    for i in range(numOfAttempts):\n        try:\n            image_path = f\"{init_img_dir}/{init_img_name}\"\n            init_img = Image.open(image_path)\n            init_img_str = img_2_b64(init_img)\n\n            \n            # # If file exists, delete it.\n            # if os.path.isfile(image_path):\n            #     os.remove(image_path)\n        except:\n            print(f\"exception:fail to read an image file {image_path}, will try again {i} of {numOfAttempts}\")\n            #sleep for one second every time you try to read an image and fail\n            time.sleep(1)\n            continue;\n    \n    \n    \n    return {\"payload\": payload,\"init_image_str\":init_img_str}\n\n@router.get('/config')\nasync def sdapi(request: Request, response: Response):\n    try:\n        \n        resp = requests.get(url=f'{sd_url}/config', params=request.query_params)\n        response.status_code = resp.status_code\n        response.body = resp.content\n    except:\n        print(f'exception: fail to send request to {sd_url}/config')\n        print(f'{request}')\n    return response\n\n@router.get('/sdapi/v1/{path:path}')\nasync def sdapi(path: str, request: Request, response: Response):\n    try:\n        \n        resp = requests.get(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params)\n        response.status_code = resp.status_code\n        response.body = resp.content\n    except:\n        print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')\n        print(f'{request}')\n    return response\n\n@router.post('/sdapi/v1/{path:path}')\nasync def sdapi(path: str, request: Request, response: Response):\n    try:\n        json = await request.json()\n    except: \n        json = {}\n\n    try:\n        # if(path ==\"interrupt\"):\n        #     resp = requests.post(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params)\n\n        # else:\n        #     resp = requests.post(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params, json=await request.json())\n        resp = requests.post(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params, json=json)\n\n        response.status_code = resp.status_code\n        response.body = resp.content\n    except:\n        print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')\n        print(f'{request}')\n    return response\n\n\n\n# async def base64ToPng(base64_image,image_path):\n#     base64_img_bytes = base64_image.encode('utf-8')\n#     with open(image_path, 'wb') as file_to_save:\n#         decoded_image_data = base64.decodebytes(base64_img_bytes)\n#         file_to_save.write(decoded_image_data)\n\n\n@router.post('/save/png/')\nasync def savePng(request:Request):\n    print(\"savePng()\")\n    try:\n        json = await request.json()\n        \n    except: \n        json = {}\n    \n    # print(\"json:\",json)\n    try:\n        folder = './init_images'\n        image_path = f\"{folder}/{json['image_name']}\"\n        await img2imgapi.base64ToPng(json['base64'],image_path)\n        \n        \n        \n        \n        return {\"status\":f\"{json['image_name']} has been saved\"}\n    except:\n        print(f'{request}')\n    return {\"error\": \"error message: could not save the image file\"}\n\n\n@router.post('/search/image/')\nasync def searchImage(request:Request):\n    try:\n        json = await request.json()\n    except: \n        json = {}\n    \n\n    try:\n        keywords = json.get('keywords','cute dogs') \n        images = await search.imageSearch(keywords)\n        print(images)\n        \n        \n        return {\"images\":images}\n    except:\n        print(\"keywords\",keywords)\n        # print(f'{request}')\n    return {\"error\": \"error message: can't preform an image search\"}\n\n@router.post('/mask/expansion/')\nasync def maskExpansionHandler(request:Request):\n    try:\n        json = await request.json()\n    except: \n        json = {}\n    \n\n    try:\n        # keywords = json.get('keywords','cute dogs') \n        base64_mask_image = json['mask']\n        mask_expansion = json['mask_expansion']\n        blur = json['blur']\n        #convert base64 to img\n        \n        await img2imgapi.base64ToPng(base64_mask_image,\"original_mask.png\")#save a copy of the mask for debugging\n\n        mask_image = img2imgapi.b64_2_img(base64_mask_image)\n        \n        expanded_mask_img = img2imgapi.maskExpansion(mask_image,mask_expansion,blur)\n        base64_expanded_mask_image = img2imgapi.img_2_b64(expanded_mask_img)\n        await img2imgapi.base64ToPng(base64_expanded_mask_image,\"expanded_mask.png\")#save a copy of the mask of the expanded_mask for debugging\n\n        print(\"successful mask expansion operation\")\n        return {\"mask\":base64_expanded_mask_image}\n    \n    except:\n        print(\"request\",request)\n        raise Exception(f\"couldn't preform mask expansion\")\n    # return response\n    return {\"error\": \"error message: can't preform an mask expansion\"}\n\n\n@router.post('/history/load')\nasync def loadHistory(request: Request):\n    # {'image_paths','metadata_setting'}\n    history = {}\n    try:\n        json = await request.json()\n    except: \n        json = {}\n\n    try:\n\n        uniqueDocumentId = json['uniqueDocumentId']\n        \n        import glob\n\n        image_paths = glob.glob(f'./output/{uniqueDocumentId}/*.png')\n        settings_paths = glob.glob(f'./output/{uniqueDocumentId}/*.json')#note: why is we are not using settings_paths?\n        print(\"loadHistory: image_paths:\", image_paths)\n        \n\n        history['image_paths'] = image_paths\n        history['metadata_jsons'] = []\n        history['base64_images'] = []\n        for image_path in image_paths:\n            print(\"image_path: \", image_path)\n            metadata_dict = metadata_to_json.createMetadataJsonFileIfNotExist(image_path)\n            history['metadata_jsons'].routerend(metadata_dict)\n            \n            \n            img = Image.open(image_path)\n            base64_image = img_2_b64(img)\n            history['base64_images'].routerend(base64_image)\n\n    except:\n        \n        print(f'{request}')\n    \n    #reverse the order so that newer generated images path will be shown first\n    \n\n    history['image_paths'].reverse()\n    history['metadata_jsons'].reverse()\n    history['base64_images'].reverse()    \n    return {\"image_paths\":history['image_paths'], \"metadata_jsons\":history['metadata_jsons'],\"base64_images\": history['base64_images']}\n\n\n@router.post('/prompt_shortcut/load')\nasync def loadPromptShortcut(request: Request):\n    prompt_shortcut_json = {}\n    try:\n        json = await request.json()\n    except: \n        json = {}\n\n    try:\n\n        prompt_shortcut_json = prompt_shortcut.load()\n        # response.body = {\"prompt_shortcut\":prompt_shortcut}\n        # response.status_code = 200\n    except:\n        # print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')\n        print(f'{request}')\n        \n    # return response\n    return {\"prompt_shortcut\":prompt_shortcut_json}\n@router.post('/prompt_shortcut/save')\nasync def loadPromptShortcut(request: Request):\n    prompt_shortcut_json = {}\n    try:\n        json = await request.json()\n    except: \n        json = {}\n\n    try:\n        # print(\"json: \",json)\n        # print(\"json['prompt_shortcut']: \",json['prompt_shortcut'])\n        # save the prompt shortcut to the prompt_shortcut.json\n        prompt_shortcut_json = json['prompt_shortcut']\n        # response.body = {\"prompt_shortcut\":prompt_shortcut}\n        # response.body = {\"prompt_shortcut\":prompt_shortcut}\n        prompt_shortcut.writeToJson(\"prompt_shortcut.json\",prompt_shortcut_json)\n    except:\n        # print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')\n        print(f'error occurred durning reading the request {request}')\n    # return response\n    return {\"prompt_shortcut\":prompt_shortcut_json}\n\n@router.post(\"/swapModel\")\nasync def swapModel(request:Request):\n    print(\"swapModel: \\n\")\n    payload = await request.json()\n    print(\"payload:\",payload)\n    model_title = payload.title\n    option_payload = {\n        # \"sd_model_checkpoint\": \"Anything-V3.0-pruned.ckpt [2700c435]\"\n        \"sd_model_checkpoint\": model_title\n\n    }\n    response = requests.post(url=f'{sd_url}/sdapi/v1/options', json=option_payload)\n\n\nimport webbrowser\n@router.post(\"/open/url/\")\nasync def openUrl(request:Request):\n    try:\n        json = await request.json()\n    except: \n        json = {}\n\n    url = \"\" \n    # print(\"json: \",json)\n    try:\n        url = json['url']\n        webbrowser.open(url)  # Go to example.com\n    except:\n        # print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')\n        print(f'an error has occurred durning processing the request {request}')\n    # return response\n    return {\"url\":url}\n\n\n@router.get('/lora/list')\nasync def list_available_loras():\n    lora_dict = {}\n    try:\n        from modules import shared\n        import glob\n\n        os.makedirs(shared.cmd_opts.lora_dir, exist_ok=True)\n\n        candidates = \\\n            glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.pt'), recursive=True) + \\\n            glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.safetensors'), recursive=True) + \\\n            glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.ckpt'), recursive=True)\n\n        for filename in sorted(candidates, key=str.lower):\n            if os.path.isdir(filename):\n                continue\n\n            name = os.path.splitext(os.path.basename(filename))[0]\n            print(\"lora name: \",name)\n            # available_loras[name] = LoraOnDisk(name, filename)\n            lora_dict[name] = name\n\n    except Exception as e:\n        print(\"list_available_loras() error \",repr(e),e)\n    return lora_dict\n\n@router.get('/vae/list')\nasync def list_available_vae():\n    sd_vae_dict = {}\n    try:\n        from modules import shared_items\n        sd_vae_dict = shared_items.sd_vae_items()\n        print(\"sd_vae_dict:\", sd_vae_dict)\n    except Exception as e:\n        print(\"list_available_vae() error \",repr(e),e)\n    return sd_vae_dict\n\n\n@router.post(\"/controlnet/filter\")\nasync def filter(keyword:str = Body('All',title=\"keyword to filter by\"),\n        preprocessor_list: List[str]= Body([],title=\"complete preprocessor list\"),\n        model_list: List[str] =Body([],title=\"complete model list\"),):\n\n\n    filtered_preprocessor_list= []\n    filtered_model_list= []\n    default_option= 'none'\n    default_model= 'None'\n\n    print(\"preprocessor_list:\",preprocessor_list)\n    print(\"model_list:\",model_list)\n    try:\n        [filtered_preprocessor_list,filtered_model_list,default_option,default_model] = global_state.filter_selected_helper(keyword,preprocessor_list,model_list)\n    except Exception as e:\n        print(\"Invalid Keyword: \",e)\n\n    return {\n        \"keywords\": list(global_state.preprocessor_filters.keys()),\n        \"module_list\": filtered_preprocessor_list,\n        \"model_list\": filtered_model_list,\n        \"default_option\":default_option,\n        \"default_model\":default_model\n    }\n    \n@router.get('/heartbeat')\nasync def heartbeat():    \n    \n    return {'heartbeat':True}\n\n\n@router.post(\"/readPngMetadata\")\nasync def readPngMetadata(request: Request):\n    try:\n        print('readPngMetadata endpoint:  ')\n        print('readPngMetadata request:  ',request)\n        contents = await request.body()\n        image = Image.open(io.BytesIO(contents))\n        \n        print(\"image.info: \",image.info)\n        return {\"metadata\":image.info}\n        \n\n    except Exception as e:\n        print(\"readPngMetadata() error \",repr(e),e)\n        return {\"status\": \"falid\"}\n\n\napp = FastAPI()\napp.include_router(router)\n"
  },
  {
    "path": "thumbnail.js",
    "content": "class Thumbnail {\n    static wrapImgInContainer(img, container_style_class) {\n        const container = document.createElement('div')\n        container.className = container_style_class\n        container.appendChild(img)\n        return container\n    }\n\n    static addSPButtonToContainer(\n        container,\n        button_id,\n        title,\n        callbackFunction,\n        param1\n    ) {\n        const elem = document.getElementById(button_id)\n        const clone = elem.cloneNode(true)\n        const button = clone\n        button.style.display = null\n        button.removeAttribute('id')\n        button.setAttribute('title', title)\n\n        // Create button element\n        button.className = 'thumbnail-image-button'\n        if (callbackFunction.constructor.name === 'AsyncFunction') {\n            button.addEventListener(\n                'click',\n                async () => await callbackFunction(param1)\n            )\n        } else {\n            button.addEventListener('click', () => callbackFunction(param1))\n        }\n\n        container.appendChild(button)\n    }\n}\n\nmodule.exports = {\n    Thumbnail,\n}\n"
  },
  {
    "path": "typescripts/@types/changedpi.d.ts",
    "content": "declare module 'changedpi'\n"
  },
  {
    "path": "typescripts/@types/custom.d.ts",
    "content": "declare module '*.svg' {\n    import React = require('react')\n    export const ReactComponent: React.FunctionComponent<\n        React.SVGProps<SVGSVGElement>\n    >\n    const src: string\n    export default src\n}\n"
  },
  {
    "path": "typescripts/@types/sdapi_py_re.d.ts",
    "content": "declare module 'sdapi_py_re' {\n    const exports: any\n    export = exports\n}\n"
  },
  {
    "path": "typescripts/@types/uxp.d.ts",
    "content": "declare module 'uxp' {\n    // Add type declarations for the uxp module here\n    export const storage: any\n    export const versions: any\n    export const host: any\n}\n"
  },
  {
    "path": "typescripts/after_detailer/after_detailer.tsx",
    "content": "import React, { ReactPropTypes } from 'react'\nimport ReactDOM from 'react-dom/client'\n\n// import { action, makeAutoObservable, reaction, toJS } from 'mobx'\nimport { observer, useObserver } from 'mobx-react'\n\nimport {\n    SliderType,\n    SpCheckBox,\n    SpMenu,\n    SpSliderWithLabel,\n} from '../util/elements'\nimport { Collapsible } from '../util/collapsible'\n// import * as sdapi from '../../sdapi_py_re'\nimport { api } from '../util/oldSystem'\nimport { AStore } from '../main/astore'\nimport { ui_config, model_list } from './config'\nconst { requestGet } = api\nimport { requestControlNetModelList } from '../controlnet/entry'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { ScriptMode } from '../util/ts/enum'\n\nimport './style/after_detailer.css'\nimport Locale from '../locale/locale'\n\ndeclare let g_sd_url: string\n\nexport let script_mode = [\n    ScriptMode.Img2Img,\n    ScriptMode.Inpaint,\n    ScriptMode.Outpaint,\n]\n\n// const configValues = Object.entries(ui_config).reduce(\n//     (acc, [key, value]) => ({ ...acc, [key]: value.value }),\n//     {}\n// )\n// const default_values: any = {\n//     _: '',\n//     ...configValues,\n// }\n\n// export const ultimate_sd_upscaler_store = new UltimateSDUpscalerStore(\n//     default_values\n// )\n\nexport const store = new AStore({\n    model_list: ui_config.ad_model.choices,\n    ad_model: ui_config.ad_model.value,\n    ad_conf: ui_config.ad_conf.value,\n    prompt: '',\n    negativePrompt: '',\n    controlnet_model: 'None',\n    controlnet_models: [] as string[],\n    controlNetWeight: 1,\n    script_name: 'adetailer',\n\n    is_installed: false,\n    is_enabled: false,\n    refresh: false,\n})\n\n@observer\nexport class AfterDetailerComponent extends React.Component<{\n    // store: AStore\n}> {\n    // slider1Ref = React.createRef<SpSliderWithLabel>()\n    // slider2Ref = React.createRef<SpSliderWithLabel>()\n    // state = {\n    //     items: ['Item 1', 'Item 2', 'Item 3'],\n    //     sd_upscalers: [],\n    // }\n\n    async componentDidMount(): Promise<void> {\n        // this.getUpscalers()\n\n        try {\n            if (await this.isInstalled()) {\n                await this.getInpaintModels()\n                store.updateProperty('refresh', false)\n            }\n        } catch (e) {\n            console.error(e)\n        }\n    }\n\n    async componentDidUpdate(\n        prevProps: ReactPropTypes,\n        prevState: ReactPropTypes\n    ) {}\n    handleRefresh = async () => {\n        if (await this.isInstalled()) {\n            await this.getInpaintModels()\n        }\n    }\n    async isInstalled() {\n        try {\n            const full_url = `${g_sd_url}/sdapi/v1/scripts`\n\n            const scripts = await requestGet(full_url)\n            const is_installed =\n                scripts?.txt2img?.includes(store.data.script_name) ||\n                scripts?.img2img?.includes(store.data.script_name) ||\n                false\n\n            console.log('is_installed: ', is_installed)\n            store.updateProperty('is_installed', is_installed)\n            return is_installed\n        } catch (e) {\n            console.error(e)\n        }\n    }\n    async getInpaintModels() {\n        try {\n            const controlnet_model_list =\n                (await requestControlNetModelList()) ?? []\n            let inpaint_models = controlnet_model_list.filter((name: string) =>\n                name.includes('inpaint')\n            )\n            inpaint_models = ['None'].concat(inpaint_models)\n            store.updateProperty('controlnet_models', inpaint_models)\n            // return inpaint_models\n        } catch (e) {\n            console.warn('getInpaintModels():', e)\n        }\n    }\n\n    render() {\n        if (!store.data.is_installed) {\n            return (\n                <div>\n                    <sp-label class=\"missing-error\">\n                        Script is not available; Make sure to install it from\n                        Automatic1111 webui\n                    </sp-label>\n                    <button\n                        className=\"btnSquare refreshButton btnResetSettings\"\n                        title=\"Refresh the ADetailer Extension\"\n                        onClick={this.handleRefresh}\n                    ></button>\n                </div>\n            )\n        }\n\n        return (\n            <div>\n                <sp-checkbox\n                    checked={store.data.is_enabled ? true : undefined}\n                    onClick={(event: React.ChangeEvent<HTMLInputElement>) => {\n                        store.updateProperty('is_enabled', event.target.checked)\n                    }}\n                >\n                    {Locale('Activate')}\n                </sp-checkbox>\n                <SpMenu\n                    title=\"model\"\n                    items={store.data.model_list}\n                    // style=\"width: 199px; margin-right: 5px\"\n                    label_item=\"Select a ADetailer Model\"\n                    // id={'model_list'}\n                    selected_index={store.data.model_list.indexOf(\n                        store.data.ad_model\n                    )}\n                    onChange={(id: any, value: any) => {\n                        console.log('onChange value: ', value)\n\n                        store.updateProperty('ad_model', value.item)\n                    }}\n                ></SpMenu>\n                <sp-textarea\n                    placeholder=\"ADetailer Prompt\"\n                    value={store.data.prompt}\n                    onInput={(\n                        event: React.ChangeEvent<HTMLTextAreaElement>\n                    ) => {\n                        store.updateProperty('prompt', event.target.value)\n                    }}\n                ></sp-textarea>\n                <sp-textarea\n                    placeholder=\"ADetailer Negative Prompt\"\n                    value={store.data.negativePrompt}\n                    onInput={(\n                        event: React.ChangeEvent<HTMLTextAreaElement>\n                    ) => {\n                        store.updateProperty(\n                            'negativePrompt',\n                            event.target.value\n                        )\n                    }}\n                ></sp-textarea>\n                <SpSliderWithLabel\n                    // id={id}\n                    show-value={false}\n                    steps={ui_config.ad_conf.step}\n                    out_min={ui_config.ad_conf.minimum}\n                    out_max={ui_config.ad_conf.maximum}\n                    output_value={store.data['ad_conf']}\n                    // title={ui_config[id].label}\n                    label=\"Detection Confidence Threshold %:\"\n                    onSliderInput={(new_value: number) => {\n                        // console.log('slider_change: ', new_value)\n                        store.updateProperty('ad_conf', new_value)\n                    }}\n                />\n                {/* <SpSliderWithLabel\n                    // id={id}\n                    show-value={false}\n                    steps={1}\n                    out_min={0}\n                    out_max={100}\n                    // output_value={this.props.store.data[id]}\n                    // title={ui_config[id].label}\n                    label=\"Mask min area ratio\"\n                    onSliderChange={(new_value: number) => {\n                        console.log('slider_change: ', new_value)\n                    }}\n                /> */}\n                <SpMenu\n                    title=\"controlnet inpaint model\"\n                    items={store.data.controlnet_models}\n                    // style=\"width: 199px; margin-right: 5px\"\n                    label_item=\"Select a ControlNet Model\"\n                    // id={'model_list'}\n                    selected_index={store.data.controlnet_models.indexOf(\n                        store.data.controlnet_model\n                    )}\n                    onChange={(id: any, value: any) => {\n                        // console.log('onChange value: ', value)\n                        store.updateProperty('controlnet_model', value.item)\n                    }}\n                ></SpMenu>\n                <SpSliderWithLabel\n                    // id={id}\n                    show-value={false}\n                    steps={ui_config.ad_controlnet_weight.step}\n                    out_min={ui_config.ad_controlnet_weight.minimum}\n                    out_max={ui_config.ad_controlnet_weight.maximum}\n                    output_value={store.data.controlNetWeight}\n                    // output_value={this.props.store.data[id]}\n                    // title={ui_config[id].label}\n                    label=\"ControlNet Weight\"\n                    slider_type={\n                        Number.isInteger(ui_config['ad_controlnet_weight'].step)\n                            ? SliderType.Integer\n                            : SliderType.Float\n                    }\n                    onSliderInput={(new_value: number) => {\n                        // console.log('slider_change: ', new_value)\n                        store.updateProperty('controlNetWeight', new_value)\n                    }}\n                />\n            </div>\n        )\n    }\n}\n\nconst domNode = document.getElementById('alwaysOnScriptsContainer')!\nconst root = ReactDOM.createRoot(domNode)\n\nroot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n            <Collapsible label={'ADetailer'}>\n                <AfterDetailerComponent />\n            </Collapsible>\n        </div>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/after_detailer/config.ts",
    "content": "let MASK_MERGE_INVERT = ['None', 'Merge', 'Merge and Invert']\n\nexport const model_list = [\n    'face_yolov8n.pt',\n    'face_yolov8s.pt',\n    'mediapipe_face_full',\n    'mediapipe_face_short',\n    'mediapipe_face_mesh',\n    'mediapipe_face_mesh_eyes_only',\n    'hand_yolov8n.pt',\n    'person_yolov8n-seg.pt',\n    'person_yolov8s-seg.pt',\n\n    'None',\n]\nexport let ui_config = {\n    ad_model: {\n        label: 'ADetailer model',\n        choices: model_list,\n        value: 'face_yolov8n.pt',\n        visible: true,\n        type: 'value',\n        elem_id: 'ad_model',\n    },\n    ad_prompt: {\n        label: 'ad_prompt',\n        show_label: false,\n        lines: 3,\n        placeholder: 'ADetailer prompt',\n        elem_id: 'ad_prompt',\n    },\n    ad_negative_prompt: {\n        label: 'ad_negative_prompt',\n        show_label: false,\n        lines: 2,\n        placeholder: 'ADetailer negative prompt',\n        elem_id: 'ad_negative_prompt',\n    },\n\n    ad_mask_min_ratio: {\n        label: 'Mask min area ratio',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.001,\n        value: 0.0,\n        visible: true,\n        elem_id: 'ad_mask_min_ratio',\n    },\n    ad_mask_max_ratio: {\n        label: 'Mask max area ratio',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.001,\n        value: 1.0,\n        visible: true,\n        elem_id: 'ad_mask_max_ratio',\n    },\n    ad_conf: {\n        label: 'Detection model confidence threshold',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.01,\n        value: 0.3,\n        visible: true,\n        elem_id: 'ad_confidence',\n    },\n    ad_x_offset: {\n        label: 'Mask x(→) offset',\n        minimum: -200,\n        maximum: 200,\n        step: 1,\n        value: 0,\n        visible: true,\n        elem_id: 'ad_x_offset',\n    },\n    ad_y_offset: {\n        label: 'Mask y(↑) offset',\n        minimum: -200,\n        maximum: 200,\n        step: 1,\n        value: 0,\n        visible: true,\n        elem_id: 'ad_y_offset',\n    },\n    ad_dilate_erode: {\n        label: 'Mask erosion (-) / dilation (+)',\n        minimum: -128,\n        maximum: 128,\n        step: 4,\n        value: 4,\n        visible: true,\n        elem_id: 'ad_dilate_erode',\n    },\n    ad_mask_merge_invert: {\n        label: 'Mask merge mode',\n        choices: MASK_MERGE_INVERT,\n        value: 'None',\n        elem_id: 'ad_mask_merge_invert',\n    },\n    ad_mask_blur: {\n        label: 'Inpaint mask blur',\n        minimum: 0,\n        maximum: 64,\n        step: 1,\n        value: 4,\n        visible: true,\n        elem_id: 'ad_mask_blur',\n    },\n    ad_denoising_strength: {\n        label: 'Inpaint denoising strength',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.01,\n        value: 0.4,\n        visible: true,\n        elem_id: 'ad_denoising_strength',\n    },\n    ad_inpaint_full_res: {\n        label: 'Inpaint only masked',\n        value: true,\n        visible: true,\n        elem_id: 'ad_inpaint_only_masked',\n    },\n    ad_inpaint_full_res_padding: {\n        label: 'Inpaint only masked padding, pixels',\n        minimum: 0,\n        maximum: 256,\n        step: 4,\n        value: 32,\n        visible: true,\n        elem_id: 'ad_inpaint_only_masked_padding',\n    },\n    ad_use_inpaint_width_height: {\n        label: 'Use separate width/height',\n        value: false,\n        visible: true,\n        elem_id: 'ad_use_inpaint_width_height',\n    },\n    ad_inpaint_width: {\n        label: 'inpaint width',\n        minimum: 64,\n        maximum: 2048,\n        step: 4,\n        value: 512,\n        visible: true,\n        elem_id: 'ad_inpaint_width',\n    },\n    ad_inpaint_height: {\n        label: 'inpaint height',\n        minimum: 64,\n        maximum: 2048,\n        step: 4,\n        value: 512,\n        visible: true,\n        elem_id: 'ad_inpaint_height',\n    },\n    ad_use_steps: {\n        label: 'Use separate steps',\n        value: false,\n        visible: true,\n        elem_id: 'ad_use_steps',\n    },\n    ad_steps: {\n        label: 'ADetailer steps',\n        minimum: 1,\n        maximum: 150,\n        step: 1,\n        value: 28,\n        visible: true,\n        elem_id: 'ad_steps',\n    },\n    ad_use_cfg_scale: {\n        label: 'Use separate CFG scale',\n        value: false,\n        visible: true,\n        elem_id: 'ad_use_cfg_scale',\n    },\n    ad_cfg_scale: {\n        label: 'ADetailer CFG scale',\n        minimum: 0.0,\n        maximum: 30.0,\n        step: 0.5,\n        value: 7.0,\n        visible: true,\n        elem_id: 'ad_cfg_scale',\n    },\n    ad_use_noise_multiplier: {\n        label: 'Use separate noise multiplier',\n        value: false,\n        visible: true,\n        elem_id: 'ad_use_noise_multiplier',\n    },\n    ad_noise_multiplier: {\n        label: 'Noise multiplier for img2img',\n        minimum: 0.5,\n        maximum: 1.5,\n        step: 0.01,\n        value: 1.0,\n        visible: true,\n        elem_id: 'ad_noise_multiplier',\n    },\n    ad_restore_face: {\n        label: 'Restore faces after ADetailer',\n        value: false,\n        elem_id: 'ad_restore_face',\n    },\n    ad_controlnet_model: {\n        label: 'ControlNet model',\n        choices: ['None'],\n        value: 'None',\n        visible: true,\n        type: 'value',\n        interactive: true,\n        elem_id: 'ad_controlnet_model',\n    },\n    ad_controlnet_weight: {\n        label: 'ControlNet weight',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.05,\n        value: 1.0,\n        visible: true,\n        interactive: true,\n        elem_id: 'ad_controlnet_weight',\n    },\n    ad_controlnet_guidance_start: {\n        label: 'ControlNet guidance start',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.01,\n        value: 1.0,\n        visible: true,\n        interactive: true,\n        elem_id: 'ad_controlnet_guidance_start',\n    },\n    ad_controlnet_guidance_end: {\n        label: 'ControlNet guidance end',\n        minimum: 0.0,\n        maximum: 1.0,\n        step: 0.01,\n        value: 1.0,\n        visible: true,\n        interactive: true,\n        elem_id: 'ad_controlnet_guidance_end',\n    },\n}\n"
  },
  {
    "path": "typescripts/after_detailer/style/after_detailer.css",
    "content": "/* Style the button that is used to open and close the collapsible content */\n.collapsible {\n    background-color: #2d2d2d;\n\n    cursor: pointer;\n    padding: 3px;\n\n    border: none;\n    text-align: left;\n    outline: none;\n    font-size: 15px;\n    font-weight: 500;\n    color: #eaeaea;\n\n    display: flex;\n    justify-content: space-between;\n    width: 100%;\n}\n\n/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */\n.collapsible-active,\n.collapsible:hover {\n    background-color: #1f1f1f;\n}\n\n.triangle {\n    background-color: transparent;\n}\n\n.truncate {\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.minimal-checkbox {\n    margin: 0;\n    padding: 0;\n    border: none;\n}\n"
  },
  {
    "path": "typescripts/comfyui/comfyapi.ts",
    "content": "import { app } from 'photoshop'\nimport settings_tab from '../settings/settings'\nimport { requestGet, requestPost } from '../util/ts/api'\nimport { base64UrlToBase64 } from '../util/ts/general'\ninterface ComfyError {\n    type: string\n    message: string\n    details: string\n    extra_info: any\n}\n\ninterface NodeError {\n    errors: ComfyError[]\n    dependent_outputs: string[]\n    class_type: string\n}\nexport interface ComfyResult {\n    error?: ComfyError\n    node_errors?: { [key: string]: NodeError }\n}\nclass ComfyAPI {\n    private object_info: Record<string, any> = {}\n    comfy_url: string\n    status: boolean = false\n\n    constructor(comfy_url: string) {\n        this.comfy_url = comfy_url\n    }\n    async init(display_error = false) {\n        try {\n            this.object_info = await this.initializeObjectInfo(this.comfy_url)\n            this.status = true\n            return this.object_info\n        } catch (e) {\n            console.error(e)\n            this.status = false\n            if (display_error) {\n                app.showAlert(`${e}`)\n            }\n        }\n    }\n    setUrl(comfy_url: string) {\n        this.comfy_url = comfy_url\n    }\n    async refresh() {\n        this.object_info = await this.initializeObjectInfo(this.comfy_url)\n    }\n    async queue() {\n        const res = await requestGet(`${this.comfy_url}/queue`)\n        const queue_running = res?.queue_running ? res?.queue_running : []\n        const queue_pending = res?.queue_pending ? res?.queue_pending : []\n        return { queue_running, queue_pending }\n    }\n    async prompt(prompt: any) {\n        try {\n            const payload = {\n                prompt: prompt,\n            }\n            const res = await requestPost(`${this.comfy_url}/prompt`, payload)\n\n            return res\n        } catch (e) {\n            console.error(e)\n        }\n    }\n\n    async getHistory(prompt_id: string = '') {\n        try {\n            const url = `${this.comfy_url}/history/${prompt_id}`\n\n            const res = await requestGet(url)\n\n            return res\n        } catch (e) {\n            console.error(e)\n        }\n    }\n    async view(\n        filename: string,\n        type: string = 'output',\n        subfolder: string = ''\n    ): Promise<string> {\n        const ab: ArrayBuffer = await requestGet(\n            `${this.comfy_url}/view?subfolder=${subfolder}&type=${type}&filename=${filename}`\n        )\n        return Buffer.from(ab).toString('base64')\n    }\n\n    async initializeObjectInfo(comfy_url: string) {\n        try {\n            const full_url = `${comfy_url}/object_info`\n            const object_info = await requestGet(full_url)\n            if (!object_info)\n                throw `can not request from comfyui url: ${comfy_url}`\n            return object_info\n        } catch (e) {\n            console.error(e)\n            throw e\n        }\n    }\n    getObjectInfo() {\n        try {\n            return this.object_info\n        } catch (e) {\n            console.error(e)\n            throw e\n        }\n    }\n    getReadableError(result: ComfyResult): string {\n        const parseError = (error: any) =>\n            `Error: ${error.message}\\n${\n                error.details ? `Details: ${error.details}\\n` : ''\n            }`\n\n        let errorMessage = result.error ? parseError(result.error) : ''\n\n        if (result.node_errors) {\n            for (const [node_id, node_error] of Object.entries(\n                result.node_errors\n            )) {\n                errorMessage += `Node ${node_id}:\\n${node_error.errors\n                    .map(parseError)\n                    .join('')}`\n            }\n        }\n        return errorMessage\n    }\n\n    private getData(path: string[]): any[] {\n        let data = []\n        try {\n            let obj = this.object_info\n            for (const p of path) {\n                obj = obj[p]\n            }\n            data = obj[0]\n        } catch (e) {\n            console.error(\n                `Failed to get data from path ${path.join('.')}: ${e}`\n            )\n        }\n        return data\n    }\n\n    getModels(): any[] {\n        return this.getData([\n            'CheckpointLoader',\n            'input',\n            'required',\n            'ckpt_name',\n        ])\n    }\n\n    getVAEs(): any[] {\n        return this.getData(['VAELoader', 'input', 'required', 'vae_name'])\n    }\n    getSamplerNames(): string[] {\n        return this.getData(['KSampler', 'input', 'required', 'sampler_name'])\n    }\n    getHiResUpscalers(): string[] {\n        return this.getData([\n            'LatentUpscaleBy',\n            'input',\n            'required',\n            'upscale_method',\n        ])\n    }\n    getLoras(): string[] {\n        return this.getData(['LoraLoader', 'input', 'required', 'lora_name'])\n    }\n    async interrupt() {\n        const res = await requestPost(`${this.comfy_url}/interrupt`, {})\n        console.log('res: ', res)\n        return res\n    }\n}\n\nexport default {\n    ComfyAPI,\n    comfy_api: new ComfyAPI(settings_tab.store.data.comfy_url),\n}\n"
  },
  {
    "path": "typescripts/comfyui/comfyui.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { requestGet, requestPost } from '../util/ts/api'\nimport { observer } from 'mobx-react'\nimport { runInAction } from 'mobx'\nimport {\n    MoveToCanvasSvg,\n    SliderType,\n    SpMenu,\n    SpSlider,\n    SpSliderWithLabel,\n    SpTextfield,\n} from '../util/elements'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { Collapsible } from '../util/collapsible'\nimport Locale from '../locale/locale'\n\nimport { Grid } from '../util/grid'\nimport { io } from '../util/oldSystem'\nimport { app, core } from 'photoshop'\nimport { reaction, toJS } from 'mobx'\nimport { host, storage } from 'uxp'\n\nimport util, {\n    ComfyInputType,\n    ComfyUINode,\n    InputTypeEnum,\n    ValidInput,\n    store,\n} from './util'\n\nimport {\n    base64UrlToBase64,\n    copyJson,\n    deleteKeys,\n    getImageFromCanvas_new,\n    isValidVersion,\n    urlToCanvas,\n} from '../util/ts/general'\nimport comfyapi from './comfyapi'\nimport { getSelectionInfoExe } from '../../psapi'\nimport { moveImageToLayer } from '../util/ts/io'\nimport { reuseOrUploadComfyImage } from './main_ui'\nimport { SetLayerColor } from '../util/ts/layer'\n\ninterface Error {\n    type: string\n    message: string\n    details: string\n    extra_info: any\n}\n\ninterface NodeError {\n    errors: Error[]\n    dependent_outputs: string[]\n    class_type: string\n}\n\ninterface Result {\n    error?: Error\n    node_errors?: { [key: string]: NodeError }\n}\n\nfunction logError(result: Result) {\n    // Top-level error\n    let has_error = false\n    let errorMessage = ''\n\n    // Top-level error\n    if (result.error) {\n        errorMessage += `Error: ${result.error.message}\\n`\n        has_error = true\n        if (result.error.details) {\n            errorMessage += `Details: ${result.error.details}\\n`\n        }\n    }\n\n    // Node errors\n    if (result.node_errors) {\n        for (const [node_id, node_error] of Object.entries(\n            result.node_errors\n        )) {\n            errorMessage += `Node ${node_id}:\\n`\n            has_error = true\n            for (const error of node_error.errors) {\n                errorMessage += `- Error: ${error.message}\\n`\n                if (error.details) {\n                    errorMessage += `  Details: ${error.details}\\n`\n                }\n            }\n        }\n    }\n\n    if (errorMessage) {\n        app.showAlert(errorMessage)\n    }\n    return has_error\n}\n\nexport async function workflowEntries() {\n    try {\n        const workflow_folder = await storage.localFileSystem.getFolder()\n\n        let entries = await workflow_folder.getEntries()\n        const workflow_entries = entries.filter(\n            // (e: any) => e.isFile && e.name.toLowerCase().includes('.png') // must be a file and has the of the type .png\n            (e: any) => e.isFile && e.name.toLowerCase().includes('.json') // must be a file and has the of the type .json\n        )\n\n        console.log('workflow_entries: ', workflow_entries)\n\n        return workflow_entries\n    } catch (e) {\n        console.error(e)\n        // throw e\n        return []\n    }\n}\nexport async function postPrompt(prompt: any) {\n    try {\n        const url = `${comfyapi.comfy_api.comfy_url}/prompt`\n        const payload = {\n            prompt: prompt,\n        }\n        const result = await requestPost(url, payload)\n\n        return result\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nconst timer = (ms: any) => new Promise((res) => setTimeout(res, ms))\n\nexport async function generateRequest(prompt: any) {\n    try {\n        const prompt_result = await postPrompt(prompt)\n        const prompt_id = prompt_result.prompt_id\n        let history_result: any\n        let numberOfAttempts = 0\n        let has_error = logError(prompt_result)\n        while (true && !has_error) {\n            try {\n                console.log('get history attempt: ', numberOfAttempts)\n                history_result = await util.getHistory(prompt_id)\n                console.log('history_result:', history_result)\n                if (history_result?.[prompt_id]) break\n\n                numberOfAttempts += 1\n                await timer(5000)\n            } catch (e) {\n                console.log('getHistory failed, retrying...')\n            }\n        }\n        return { history_result: history_result, prompt_id: prompt_id }\n    } catch (e) {\n        console.error(e)\n    }\n}\nexport async function generateImage(prompt: any) {\n    try {\n        let { history_result, prompt_id }: any = await generateRequest(prompt)\n\n        const outputs: any[] = Object.values(history_result[prompt_id].outputs)\n        const images: any[] = []\n        for (const output of outputs) {\n            if (Array.isArray(output.images)) {\n                images.push(...output.images)\n            }\n        }\n\n        const base64_imgs = []\n        const formats: string[] = []\n\n        for (const image of images) {\n            const img = await comfyapi.comfy_api.view(\n                image.filename,\n                image.type,\n                image.subfolder\n            )\n            base64_imgs.push(img)\n            formats.push(util.getFileFormat(image.filename))\n        }\n\n        store.data.comfyui_output_images = base64_imgs\n\n        const thumbnails = []\n        for (let i = 0; i < base64_imgs.length; ++i) {\n            if (['png', 'webp', 'jpg'].includes(formats[i])) {\n                thumbnails.push(await io.createThumbnail(base64_imgs[i], 300))\n            } else if (['gif'].includes(formats[i])) {\n                thumbnails.push('data:image/gif;base64,' + base64_imgs[i])\n            }\n        }\n\n        store.data.comfyui_output_thumbnail_images = thumbnails\n\n        return base64_imgs\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport async function getConfig() {\n    //TODO: replace this method with get_object_info from comfyapi\n    try {\n        const prompt = {\n            '1': {\n                inputs: {},\n                class_type: 'GetConfig',\n            },\n        }\n\n        let { history_result, prompt_id }: any = await generateRequest(prompt)\n        //@ts-ignore\n        const config: ComfyUIConfig = Object.values(\n            history_result?.[prompt_id].outputs\n        )[0]\n        store.data.comfyui_config = { ...config }\n        store.data.comfyui_config.valid_nodes = JSON.parse(\n            config.valid_nodes.join('')\n        )\n\n        return config\n    } catch (e) {\n        console.error(e)\n    }\n}\nexport async function getWorkflowApi(image_path: string) {\n    try {\n        const prompt = {\n            '1': {\n                inputs: {\n                    // image: 'C:/Users/abdul/Downloads/img2img_workflow.png',\n                    image_path: image_path,\n                },\n                class_type: 'LoadImageWithMetaData',\n            },\n        }\n        let { history_result, prompt_id }: any = await generateRequest(prompt)\n        //@ts-ignore\n        let { prompt: result_prompt, workflow } = Object.values(\n            history_result?.[prompt_id].outputs\n        )[0]\n        result_prompt = JSON.parse(result_prompt.join(''))\n        workflow = JSON.parse(workflow.join(''))\n\n        return { prompt: result_prompt, workflow }\n    } catch (e) {\n        console.error(e)\n    }\n}\nfunction filterObjectProperties(node_inputs: any, valid_keys: string[]) {\n    return Object.fromEntries(\n        valid_keys.map((key: string) => [key, node_inputs[key]])\n    )\n}\nexport function parseUIFromNode(node: ComfyUINode, node_id: string) {\n    //convert node to array of ui element definition\n    try {\n        const ValidNodes = store.data.comfyui_config?.valid_nodes\n        const valid_ui = ValidNodes[node.class_type]?.inputs // all the valid inputs of a node\n        const list_ids = ValidNodes[node.class_type]?.list_id\n        if (valid_ui) {\n            const keys = Object.keys(valid_ui)\n            const filtered_values = filterObjectProperties(node.inputs, keys)\n            const entires = keys.map((key) => {\n                //example values:\n                // \"sampler_name\": {\n                // \"label\": \"sampler_name\",\n                // \"value\": \"dpmpp_2m\",\n                // \"type\": \"Menu\",\n                // \"list_id\": \"samplers\"\n                // },\n\n                return [\n                    key,\n                    {\n                        label: key,\n                        value: filtered_values[key],\n                        type: valid_ui[key],\n                        list_id: list_ids?.[key],\n                        node_id: node_id,\n                    },\n                ]\n            })\n\n            const valid_node_input = Object.fromEntries(entires)\n            store.data.comfyui_valid_nodes[node_id] = valid_node_input\n            store.data.uuids[node_id] = window.crypto.randomUUID()\n            return valid_node_input\n        }\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport function storeToPrompt(store: any, basePrompt: any) {\n    //TODO change .map to .forEach\n    let modified_prompt = { ...basePrompt } // the original prompt but with the value of the ui\n    Object.entries(store.data.comfyui_valid_nodes).forEach(\n        ([node_id, node_inputs]: [string, any]) => {\n            Object.entries(node_inputs).forEach(\n                ([input_id, node_input]: [string, any]) => {\n                    return (modified_prompt[node_id]['inputs'][input_id] =\n                        node_input.value)\n                }\n            )\n        }\n    )\n    // store.data.\n    // modified_propmt[load_image_node_id]\n    // prompt = { ...store.data.comfyui_valid_nodes }\n\n    return modified_prompt\n}\nfunction createMenu(input: ValidInput) {\n    console.log('input: ', toJS(input))\n    return (\n        <>\n            <sp-label\n                class=\"title\"\n                style={{ width: '60px', display: 'inline-block' }}\n            >\n                {input.label}\n            </sp-label>\n            <SpMenu\n                size=\"m\"\n                title=\"input.label\"\n                items={store.data.comfyui_config[input.list_id]}\n                label_item={`Select ${input.label}`}\n                selected_index={store.data.comfyui_config[\n                    input.list_id\n                ]!.indexOf(input.value)}\n                onChange={(id: any, value: any) => {\n                    input.value = value.item\n                }}\n            ></SpMenu>\n        </>\n    )\n}\n\nfunction createTextField(input: ValidInput) {\n    let element = (\n        <>\n            <sp-label>{input.label}</sp-label>\n            <SpTextfield\n                style={{ width: '100%' }}\n                title=\"\"\n                type={input.type.includes('number') ? 'number' : 'text'}\n                placeholder=\"\"\n                value={input.value}\n                onChange={(evt: any) => {\n                    input.value = evt.target.value\n                }}\n            ></SpTextfield>\n        </>\n    )\n    return element\n}\nfunction createTextArea(input: ValidInput) {\n    let element = (\n        <>\n            <sp-label>{input.label}</sp-label>\n            <sp-textarea\n                onInput={(event: any) => {\n                    input.value = event.target.value\n                }}\n                placeholder={`${input.label}`}\n                value={input.value}\n            ></sp-textarea>\n        </>\n    )\n    return element\n}\nfunction createImageBase64(input: ValidInput) {\n    let element = (\n        <>\n            <div>\n                <img\n                    className=\"column-item-image\"\n                    src={\n                        // store.data.load_image_base64_strings?.[input.node_id]\n                        input.value\n                            ? 'data:image/png;base64,' +\n                              //   store.data.load_image_base64_strings?.[\n                              //       input.node_id\n                              //   ]\n                              input.value\n                            : 'https://source.unsplash.com/random'\n                    }\n                    width=\"300px\"\n                    height=\"100px\"\n                />\n            </div>\n            <div className=\"imgButton\">\n                <button\n                    className=\"column-item button-style btnSquare\"\n                    onClick={async () => {\n                        input.value = await io.getImg2ImgInitImage()\n                    }}\n                    title=\"\"\n                >\n                    {Locale('Set Image')}\n                </button>\n            </div>\n        </>\n    )\n    return element\n}\nfunction nodeInputToHtmlElement(input: ValidInput) {\n    let element\n    if (\n        [InputTypeEnum.NumberField, InputTypeEnum.TextField].includes(\n            input.type\n        )\n    ) {\n        element = createTextField(input)\n    } else if ([InputTypeEnum.Menu].includes(input.type)) {\n        element = createMenu(input)\n    } else if ([InputTypeEnum.TextArea].includes(input.type)) {\n        element = createTextArea(input)\n    } else if ([InputTypeEnum.ImageBase64].includes(input.type)) {\n        element = createImageBase64(input)\n    }\n    return element\n}\n\nexport async function loadWorkflow(workflow_path: string) {\n    try {\n        store.data.current_prompt = (\n            await getWorkflowApi(workflow_path)\n        )?.prompt\n\n        store.data.is_random_seed = Object.fromEntries(\n            Object.keys(toJS(store.data.current_prompt)).map(\n                (node_id: string) => {\n                    return [node_id, false]\n                }\n            )\n        )\n        const current_prompt: any = store.toJsFunc().data.current_prompt\n        const loadImageNodes = Object.keys(current_prompt)\n            .filter(\n                (key: any) => current_prompt[key].class_type === 'LoadImage'\n            )\n            .reduce(\n                (acc, key) => ({\n                    ...acc,\n                    [key]: current_prompt[key],\n                }),\n                {}\n            )\n\n        Object.keys(loadImageNodes).forEach((node_id: any) => {\n            store.data.current_prompt[node_id] = {\n                inputs: {\n                    image_base64: '',\n                },\n                class_type: 'LoadImageBase64',\n            }\n        })\n\n        const node_obj = Object.entries(store.data.current_prompt)\n        //clear both node structure and base64 images store values\n        store.data.comfyui_valid_nodes = {}\n        store.data.uuids = {}\n        // store.data.load_image_base64_strings = {}\n        node_obj.forEach(([node_id, node]: [string, any]) => {\n            console.log(node_id, node)\n            const valid_input = parseUIFromNode(node, node_id)\n        })\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nfunction setSliderValue(store: any, node_id: string, name: string, value: any) {\n    runInAction(() => {\n        store.data.current_prompt2[node_id].inputs[name] = value\n    })\n}\nasync function onChangeLoadImage(\n    node_id: string,\n    filename: string,\n    type = 'input'\n) {\n    try {\n        store.data.current_uploaded_image[node_id] =\n            await util.base64UrlFromComfy({\n                filename: encodeURIComponent(filename),\n                type: type,\n                subfolder: 'Auto-Photoshop-SD',\n            })\n        store.data.current_prompt2[node_id].inputs.image = `${filename}`\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function onChangeLoadVideo(\n    node_id: string,\n    filename: string,\n    type = 'input'\n) {\n    try {\n        store.data.current_uploaded_video[node_id] =\n            await util.base64UrlFromComfy({\n                filename: encodeURIComponent(filename),\n                type: type,\n                subfolder: 'Auto-Photoshop-SD',\n            })\n        store.data.current_prompt2[node_id].inputs.video = filename\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction renderNode(node_id: string, node: any, is_output: boolean) {\n    const comfy_node_info = toJS(store.data.object_info[node.class_type])\n\n    // console.log('comfy_node_info: ', comfy_node_info)\n    const node_type = util.getNodeType(node.class_type)\n    let node_html\n\n    const inputs = toJS(node.inputs)\n    node_html = Object.entries(inputs).map(([name, value], index) => {\n        // store.data.current_prompt2[node_id].inputs[name] = value\n        try {\n            const input = comfy_node_info.input.required[name]\n\n            let { type, config } = util.parseComfyInput(name, input, value)\n            if (type === ComfyInputType.Skip) {\n                return (\n                    <div\n                        key={`${node_id}_${name}_${type}_${index}`}\n                        style={{ display: 'none' }}\n                    ></div>\n                )\n            }\n            const html_element = renderInput(\n                node_id,\n                name,\n                type,\n                config,\n                `${node_id}_${name}_${type}_${index}`\n            )\n\n            return html_element\n        } catch (e) {\n            console.error(e)\n            return (\n                <div key={`${node_id}_${name}__${index}` ?? void 0}>\n                    {/* {name},{type}, {JSON.stringify(config)} */}\n                </div>\n            )\n        }\n    })\n\n    if (node_type === util.ComfyNodeType.LoadImage) {\n        const uploaded_images = store.data.uploaded_images_list\n        const inputs = store.data.current_prompt2[node_id].inputs\n        const node_name = node.class_type\n        node_html = (\n            <div>\n                {/* New load image component */}\n                <div>\n                    <div>\n                        <sp-radio-group\n                            style={{ display: 'flex' }}\n                            // selected={ }\n                            onClick={(event: any) => {\n                                store.data.loadImage_loading_method[\n                                    node_id\n                                ].method = event.target.value\n                            }}\n                        >\n                            <sp-label slot=\"label\">\n                                {Locale('Image Loading Method:')}\n                            </sp-label>\n                            {[\n                                'Manual',\n                                'Sync From Whole Canvas',\n                                'Sync From a Layer',\n                            ].map((loading_method: string, index: number) => {\n                                return (\n                                    <sp-radio\n                                        key={`${loading_method}-loading_method-${index}`}\n                                        checked={\n                                            store.data.loadImage_loading_method[\n                                                node_id\n                                            ].method === loading_method\n                                                ? true\n                                                : void 0\n                                        }\n                                        value={loading_method}\n                                    >\n                                        {Locale(loading_method)}\n                                    </sp-radio>\n                                )\n                            })}\n                        </sp-radio-group>\n                    </div>\n                    <div\n                        style={{\n                            display:\n                                store.data.loadImage_loading_method[node_id]\n                                    .method === 'Manual'\n                                    ? void 0\n                                    : 'none',\n                        }}\n                    >\n                        <button\n                            className=\"btnSquare \"\n                            onClick={async () => {\n                                const image_base64 =\n                                    await io.getImageFromCanvas(false)\n\n                                const image_name =\n                                    await reuseOrUploadComfyImage(\n                                        image_base64,\n                                        store.data\n                                            .base64_to_uploaded_images_names,\n                                        'input'\n                                    )\n                                // const new_loaded_image = await util.uploadImage(\n                                //     false,\n                                //     image_base64,\n                                //     'temp'\n                                // )\n                                // console.log('new_loaded_image: ', new_loaded_image)\n                                if (image_name) {\n                                    // store.data.uploaded_images_list = [\n                                    //     ...store.data.uploaded_images_list,\n                                    //     image_name,\n                                    // ]\n\n                                    await onChangeLoadImage(\n                                        node_id,\n                                        image_name,\n                                        'input'\n                                    )\n                                }\n                            }}\n                        >\n                            Load Image From Canvas\n                        </button>\n                        <button\n                            className=\"btnSquare\"\n                            onClick={async () => {\n                                const new_uploaded_image =\n                                    await util.uploadImage(true, '', 'input')\n                                console.log(\n                                    'new_loaded_image: ',\n                                    new_uploaded_image\n                                )\n                                if (new_uploaded_image) {\n                                    store.data.uploaded_images_list = [\n                                        ...store.data.uploaded_images_list,\n                                        new_uploaded_image.name,\n                                    ]\n                                    await onChangeLoadImage(\n                                        node_id,\n                                        new_uploaded_image.name,\n                                        'input'\n                                    )\n                                }\n                            }}\n                        >\n                            Load Image From Folder\n                        </button>\n                    </div>\n                    <div\n                        style={{\n                            display:\n                                store.data.loadImage_loading_method[node_id]\n                                    .method === 'Sync From a Layer'\n                                    ? void 0\n                                    : 'none',\n                        }}\n                    >\n                        <button\n                            className=\"btnSquare\"\n                            onClick={async () => {\n                                const current_layer =\n                                    app.activeDocument.activeLayers[0]\n                                if (current_layer && current_layer.id) {\n                                    store.data.loadImage_loading_method[\n                                        node_id\n                                    ].data = { layer_id: current_layer.id }\n                                    await core.executeAsModal(\n                                        async () => {\n                                            await SetLayerColor()\n                                        },\n                                        { commandName: 'Color Code layer' }\n                                    )\n                                }\n                            }}\n                        >\n                            Sync Current Layer\n                        </button>\n                    </div>\n                </div>\n                <sp-label class=\"title\" style={{ display: 'inline-block' }}>\n                    {node_name}\n                </sp-label>\n                <div>\n                    <SpMenu\n                        disabled={store.data.can_edit_nodes ? true : void 0}\n                        size=\"m\"\n                        title={node_name}\n                        items={uploaded_images}\n                        label_item={`Select an Image`}\n                        // id={'model_list'}\n                        selected_index={uploaded_images.indexOf(inputs.image)}\n                        onChange={async (\n                            id: any,\n                            { index, item }: Record<string, any>\n                        ) => {\n                            console.log('onChange value.item: ', item)\n                            inputs.image = item\n                            //load image store for each LoadImage Node\n                            //use node_id to store these\n\n                            onChangeLoadImage(node_id, item, 'input')\n                        }}\n                    ></SpMenu>\n                </div>\n                <div>\n                    <button\n                        onClick={() => {\n                            let index: number = uploaded_images.indexOf(\n                                inputs.image\n                            )\n                            index--\n                            const length = uploaded_images.length\n                            index = ((index % length) + length) % length\n                            inputs.image = uploaded_images[index]\n                            onChangeLoadImage(node_id, inputs.image, 'input')\n                        }}\n                    >\n                        {' '}\n                        {'<'}{' '}\n                    </button>\n\n                    <button\n                        onClick={() => {\n                            let index: number = uploaded_images.indexOf(\n                                inputs.image\n                            )\n                            index++\n                            const length = uploaded_images.length\n                            index = ((index % length) + length) % length\n                            inputs.image = uploaded_images[index]\n                            onChangeLoadImage(node_id, inputs.image, 'input')\n                        }}\n                    >\n                        {' '}\n                        {'>'}{' '}\n                    </button>\n                </div>\n                <img\n                    src={store.data.current_uploaded_image[node_id]}\n                    style={{ height: '200px' }}\n                    onError={async () => {\n                        console.error(\n                            'error loading image: ',\n                            store.data.current_uploaded_image[node_id]\n                        )\n\n                        onChangeLoadImage(node_id, inputs.image, 'input')\n                    }}\n                />\n            </div>\n        )\n    } else if (node_type === util.ComfyNodeType.LoadVideo) {\n        //ToDo: rewrite this to support video loading node\n        const uploaded_video_list = store.data.uploaded_video_list\n        const inputs = store.data.current_prompt2[node_id].inputs\n        const node_name = node.class_type\n        node_html = (\n            <div>\n                {/* New load Video component */}\n                <div>\n                    <button\n                        className=\"btnSquare\"\n                        onClick={async () => {\n                            const new_uploaded_video = await util.uploadImage(\n                                true,\n                                '',\n                                'input'\n                            )\n                            console.log(\n                                'new_uploaded_video: ',\n                                new_uploaded_video\n                            )\n                            if (new_uploaded_video) {\n                                store.data.uploaded_video_list = [\n                                    ...store.data.uploaded_video_list,\n                                    new_uploaded_video.name,\n                                ]\n                                await onChangeLoadVideo(\n                                    node_id,\n                                    new_uploaded_video.name,\n                                    'input'\n                                )\n                            }\n                        }}\n                    >\n                        Load Image From Folder\n                    </button>\n                </div>\n                <sp-label class=\"title\" style={{ display: 'inline-block' }}>\n                    {node_name}\n                </sp-label>\n                <div>\n                    <SpMenu\n                        disabled={store.data.can_edit_nodes ? true : void 0}\n                        size=\"m\"\n                        title={node_name}\n                        items={uploaded_video_list}\n                        label_item={`Select a Video`}\n                        // id={'model_list'}\n                        selected_index={uploaded_video_list.indexOf(\n                            inputs.video\n                        )}\n                        onChange={async (\n                            id: any,\n                            { index, item }: Record<string, any>\n                        ) => {\n                            console.log('onChange value.item: ', item)\n                            inputs.video = item\n\n                            onChangeLoadVideo(node_id, item)\n                        }}\n                    ></SpMenu>\n                </div>\n                <div>\n                    <button\n                        onClick={() => {\n                            let index: number = uploaded_video_list.indexOf(\n                                inputs.video\n                            )\n                            index--\n                            const length = uploaded_video_list.length\n                            index = ((index % length) + length) % length\n                            inputs.video = uploaded_video_list[index]\n                            onChangeLoadVideo(node_id, inputs.video)\n                        }}\n                    >\n                        {' '}\n                        {'<'}{' '}\n                    </button>\n\n                    <button\n                        onClick={() => {\n                            let index: number = uploaded_video_list.indexOf(\n                                inputs.video\n                            )\n                            index++\n                            const length = uploaded_video_list.length\n                            index = ((index % length) + length) % length\n                            inputs.video = uploaded_video_list[index]\n                            onChangeLoadVideo(node_id, inputs.video)\n                        }}\n                    >\n                        {' '}\n                        {'>'}{' '}\n                    </button>\n                </div>\n                <img\n                    src={store.data.current_uploaded_video[node_id]}\n                    style={{ height: '200px' }}\n                    onError={async () => {\n                        console.error(\n                            'error loading video: ',\n                            store.data.current_uploaded_video[node_id]\n                        )\n\n                        onChangeLoadVideo(node_id, inputs.video)\n                    }}\n                />\n            </div>\n        )\n    }\n\n    if (is_output) {\n        const output_node_element = (\n            <div>\n                {node_html}\n                {store.data.current_prompt2_output[node_id]?.length > 0 ? (\n                    <>\n                        <SpSlider\n                            disabled={store.data.can_edit_nodes ? true : void 0}\n                            style={{ display: 'block' }}\n                            show-value=\"false\"\n                            id=\"slUpscaleSize\"\n                            min=\"25\"\n                            max=\"600\"\n                            value={\n                                store.data.output_thumbnail_image_size[node_id]\n                            }\n                            title=\"\"\n                            onInput={(evt: any) => {\n                                store.data.output_thumbnail_image_size[\n                                    node_id\n                                ] = evt.target.value\n                            }}\n                        >\n                            <sp-label slot=\"label\" class=\"title\">\n                                Thumbnail Size:\n                            </sp-label>\n                            <sp-label class=\"labelNumber\" slot=\"label\">\n                                {parseInt(\n                                    store.data.output_thumbnail_image_size[\n                                        node_id\n                                    ] as any\n                                )}\n                            </sp-label>\n                        </SpSlider>\n                        <sp-checkbox\n                            checked={\n                                store.data.output_node_fixed_height[node_id]\n                                    ? true\n                                    : void 0\n                            }\n                            onClick={(evt: any) => {\n                                // store.data.use_sharp_mask = evt.target.checked\n\n                                store.data.output_node_fixed_height[node_id] =\n                                    evt.target.checked\n                            }}\n                        >\n                            {Locale('Fixed Height:')}\n                        </sp-checkbox>\n                    </>\n                ) : (\n                    void 0\n                )}\n                <Grid\n                    // thumbnails_data={store.data.images}\n\n                    thumbnails={store.data.current_prompt2_output[node_id]}\n                    width={store.data.output_thumbnail_image_size[node_id]}\n                    height={200}\n                    fixedHeight={store.data.output_node_fixed_height[node_id]}\n                    action_buttons={[\n                        {\n                            ComponentType: MoveToCanvasSvg,\n                            callback: (index: number) => {\n                                let format = util.extractFormat(\n                                    store.data.current_prompt2_output[node_id][\n                                        index\n                                    ]\n                                )\n\n                                if (format === 'gif') {\n                                    //@ts-ignore\n                                    openFileFromUrlExe(\n                                        store.data.current_prompt2_output[\n                                            node_id\n                                        ][index],\n                                        format\n                                    )\n                                } else if (format === 'png') {\n                                    urlToCanvas(\n                                        store.data.current_prompt2_output[\n                                            node_id\n                                        ][index],\n                                        'comfy_output.png'\n                                    )\n                                }\n                            },\n                            title: 'Copy Image to Canvas',\n                        },\n                        {\n                            ComponentType: MoveToCanvasSvg,\n                            callback: async (index: number) => {\n                                let format = util.extractFormat(\n                                    store.data.current_prompt2_output[node_id][\n                                        index\n                                    ]\n                                )\n\n                                if (format === 'png') {\n                                    const selectionInfo =\n                                        await getSelectionInfoExe()\n                                    const image_layer = await moveImageToLayer(\n                                        base64UrlToBase64(\n                                            store.data.current_prompt2_output[\n                                                node_id\n                                            ][index]\n                                        ),\n                                        selectionInfo\n                                    )\n                                }\n                            },\n                            title: 'Copy Image to Selection Area',\n                        },\n                    ]}\n                ></Grid>\n            </div>\n        )\n\n        return output_node_element\n    }\n    return node_html\n}\nfunction renderInput(\n    node_id: string,\n    name: string,\n    type: any,\n    config: any,\n    key?: string\n) {\n    let html_element = (\n        <div key={key ?? void 0}>\n            {name},{type}, {JSON.stringify(config)}\n        </div>\n    )\n    const inputs = store.data.current_prompt2[node_id].inputs\n\n    if (type === util.ComfyInputType.Seed) {\n        html_element = (\n            <>\n                <sp-label slot=\"label\">{name}:</sp-label>\n                <sp-textfield\n                    disabled={store.data.can_edit_nodes ? true : void 0}\n                    // key={key ?? void 0}\n                    type=\"text\"\n                    // placeholder=\"cute cats\"\n                    // value={config.default}\n                    value={inputs[name]}\n                    onInput={(event: any) => {\n                        // store.data.search_query = event.target.value\n                        inputs[name] = event.target.value\n                        console.log(`${name}: ${event.target.value}`)\n                    }}\n                ></sp-textfield>\n                <button\n                    style={{\n                        width: '26px',\n                    }}\n                    className=\"btnSquare\"\n                    onClick={() => {\n                        inputs[name] = (\n                            BigInt(inputs[name]) - BigInt(1)\n                        ).toString()\n                    }}\n                >\n                    {'<'}\n                </button>\n                <button\n                    style={{\n                        width: '26px',\n                    }}\n                    className=\"btnSquare\"\n                    onClick={() => {\n                        inputs[name] = (\n                            BigInt(inputs[name]) + BigInt(1)\n                        ).toString()\n                    }}\n                >\n                    {'>'}\n                </button>\n                <sp-checkbox\n                    title=\"randomize seed before generation\"\n                    value={store.data.is_random_seed[node_id]}\n                    onClick={(evt: any) => {\n                        store.data.is_random_seed[node_id] = evt.target.checked\n                    }}\n                    style={{ display: 'inline-flex' }}\n                >\n                    random\n                </sp-checkbox>\n            </>\n        )\n    } else if (type === util.ComfyInputType.BigNumber) {\n        html_element = (\n            <>\n                <sp-label slot=\"label\">{name}:</sp-label>\n                <sp-textfield\n                    disabled={store.data.can_edit_nodes ? true : void 0}\n                    // key={key ?? void 0}\n                    type=\"text\"\n                    // placeholder=\"cute cats\"\n                    // value={config.default}\n                    value={inputs[name]}\n                    onInput={(event: any) => {\n                        // store.data.search_query = event.target.value\n                        inputs[name] = event.target.value\n                        console.log(`${name}: ${event.target.value}`)\n                    }}\n                ></sp-textfield>\n            </>\n        )\n    } else if (type === util.ComfyInputType.TextFieldNumber) {\n        html_element = (\n            <>\n                <sp-label slot=\"label\">{name}:</sp-label>\n                <SpTextfield\n                    disabled={store.data.can_edit_nodes ? true : void 0}\n                    type=\"text\"\n                    // value={config.default}\n                    value={inputs[name]}\n                    onChange={(e: any) => {\n                        const v = e.target.value\n                        let new_value =\n                            v !== ''\n                                ? Math.max(config.min, Math.min(config.max, v))\n                                : v\n                        inputs[name] = new_value\n\n                        console.log(`${name}: ${e.target.value}`)\n                    }}\n                ></SpTextfield>\n            </>\n        )\n    } else if (type === util.ComfyInputType.Slider) {\n        html_element = (\n            <SpSliderWithLabel\n                // key={key ?? void 0}\n                disabled={store.data.can_edit_nodes ? true : void 0}\n                show-value={false}\n                steps={config?.step ?? 1}\n                out_min={config?.min ?? 0}\n                out_max={config?.max ?? 100}\n                output_value={store.data.current_prompt2[node_id].inputs[name]}\n                label={name}\n                slider_type={\n                    config?.step && !Number.isInteger(config?.step)\n                        ? SliderType.Float\n                        : SliderType.Integer\n                }\n                onSliderInput={(new_value: number) => {\n                    // inputs[name] = new_value\n                    // setSliderValue(store, node_id, name, new_value)\n                    store.data.current_prompt2[node_id].inputs[name] = new_value\n                    console.log('slider_change: ', new_value)\n                }}\n            />\n        )\n    } else if (type === util.ComfyInputType.Menu) {\n        html_element = (\n            <>\n                <sp-label class=\"title\" style={{ display: 'inline-block' }}>\n                    {name}\n                </sp-label>\n                <SpMenu\n                    disabled={store.data.can_edit_nodes ? true : void 0}\n                    size=\"m\"\n                    title={inputs[name]}\n                    items={config}\n                    label_item={`Select a ${name}`}\n                    // id={'model_list'}\n                    selected_index={config.indexOf(inputs[name])}\n                    onChange={(\n                        id: any,\n                        { index, item }: Record<string, any>\n                    ) => {\n                        console.log('onChange value.item: ', item)\n                        inputs[name] = item\n                    }}\n                ></SpMenu>\n            </>\n        )\n    } else if (type === util.ComfyInputType.TextArea) {\n        html_element = (\n            <sp-textarea\n                disabled={store.data.can_edit_nodes ? true : void 0}\n                // key={key}\n                onInput={(event: any) => {\n                    try {\n                        // this.changePositivePrompt(\n                        //     event.target.value,\n                        //     store.data.current_index\n                        // )\n                        // autoResize(\n                        //     event.target,\n                        //     store.data.positivePrompts[\n                        //         store.data.current_index\n                        //     ]\n                        // )\n                        inputs[name] = event.target.value\n                    } catch (e) {\n                        console.warn(e)\n                    }\n                }}\n                placeholder={`${name}`}\n                value={inputs[name]}\n            ></sp-textarea>\n        )\n    } else if (type === util.ComfyInputType.TextField) {\n        html_element = (\n            <>\n                <sp-label slot=\"label\">{name}:</sp-label>\n\n                <SpTextfield\n                    disabled={store.data.can_edit_nodes ? true : void 0}\n                    type=\"text\"\n                    // value={config.default}\n                    value={inputs[name]}\n                    onChange={(e: any) => {\n                        inputs[name] = e.target.value\n                        console.log(`${name}: ${e.target.value}`)\n                    }}\n                ></SpTextfield>\n            </>\n        )\n    } else if (type === util.ComfyInputType.CheckBox) {\n        html_element = (\n            <>\n                {/* <sp-label slot=\"label\">{name}:</sp-label> */}\n\n                <sp-checkbox\n                    disabled={store.data.can_edit_nodes ? true : void 0}\n                    title={name}\n                    // value={inputs[name]}\n                    checked={inputs[name] ? true : void 0}\n                    onClick={(evt: any) => {\n                        inputs[name] = evt.target.checked\n                    }}\n                    style={{ display: 'inline-flex' }}\n                >\n                    {name}\n                </sp-checkbox>\n            </>\n        )\n    }\n\n    return <div key={key}>{html_element}</div>\n}\n\nexport function swap(index1: number, index2: number) {\n    const { length } = store.data.nodes_order\n    if (index1 >= 0 && index1 < length && index2 >= 0 && index2 < length) {\n        ;[store.data.nodes_order[index1], store.data.nodes_order[index2]] = [\n            store.data.nodes_order[index2],\n            store.data.nodes_order[index1],\n        ]\n    }\n}\n\nexport function moveToTop(index: number) {\n    const { length } = store.data.nodes_order\n    if (index >= 0 && index < length) {\n        const node = store.data.nodes_order[index]\n        // Remove the node from its current position\n        store.data.nodes_order.splice(index, 1)\n        // Add the node to the topmost position\n        store.data.nodes_order.unshift(node)\n    }\n}\nexport function moveToBottom(index: number) {\n    const { length } = store.data.nodes_order\n    if (index >= 0 && index < length) {\n        const node = store.data.nodes_order[index]\n        // Remove the node from its current position\n        store.data.nodes_order.splice(index, 1)\n        // Add the node to the bottommost position\n        store.data.nodes_order.push(node)\n    }\n}\n\nexport function saveWorkflowData(\n    workflow_name: string,\n    { prompt, nodes_order, nodes_label }: WorkflowData\n) {\n    storage.localStorage.setItem(\n        workflow_name,\n        JSON.stringify({ prompt, nodes_order, nodes_label })\n    )\n}\nexport function loadWorkflowData(workflow_name: string): WorkflowData {\n    const workflow_data: WorkflowData = JSON.parse(\n        storage.localStorage.getItem(workflow_name)\n    )\n    return workflow_data\n}\ninterface WorkflowData {\n    prompt: any\n    nodes_order: string[]\n    nodes_label: Record<string, string>\n}\n\nfunction resetWorkflowData(workflow_name: string) {\n    let workflow_data = JSON.parse(storage.localStorage[workflow_name])\n    const original_workflow = store.data.workflows2[workflow_name]\n    const prompt = toJS(original_workflow)\n    workflow_data['prompt'] = prompt\n\n    store.data.current_prompt2 = {}\n\n    storage.localStorage.setItem(workflow_name, JSON.stringify(workflow_data))\n\n    setTimeout(() => {\n        loadWorkflow2(toJS(store.data.workflows2[workflow_name]))\n    }, 250)\n}\nfunction loadWorkflow2(workflow: any) {\n    try {\n        //1) get prompt\n        store.data.current_prompt2 = copyJson(workflow)\n        store.data.current_uploaded_image = {}\n        // store.data.sync_from_canvas = {}\n        store.data.loadImage_loading_method = {}\n        store.data.output_node_fixed_height = {}\n        //2)  get the original order\n        store.data.nodes_order = Object.keys(toJS(store.data.current_prompt2))\n\n        //3) get labels for each nodes\n        store.data.nodes_label = Object.fromEntries(\n            Object.entries(toJS(store.data.current_prompt2)).map(\n                ([node_id, node]: [string, any]) => {\n                    if (!(node.class_type in store.data.object_info)) {\n                        throw new Error(\n                            `ComfyUI Node of type \"${node.class_type}\" is not found. Please ensure it is installed via the ComfyUI Manager.`\n                        )\n                    }\n\n                    return [\n                        node_id,\n                        toJS(store.data.object_info[node.class_type])\n                            .display_name,\n                    ]\n                }\n            )\n        )\n        store.data.is_random_seed = Object.fromEntries(\n            Object.keys(toJS(store.data.current_prompt2)).map(\n                (node_id: string) => {\n                    return [node_id, false]\n                }\n            )\n        )\n\n        for (const node_id in store.data.current_prompt2) {\n            if (\n                store.data.current_prompt2[node_id].class_type === 'LoadImage'\n            ) {\n                // store.data.sync_from_canvas[node_id] = true\n                store.data.loadImage_loading_method[node_id] = {\n                    method: 'Manual',\n                }\n            }\n        }\n\n        // parse the output nodes\n        // Note: we can't modify the node directly in the prompt like we do for input nodes.\n        //.. since this data doesn't exist on the prompt. so we create separate container for the output images\n        store.data.current_prompt2_output = Object.entries(\n            store.data.current_prompt2\n        ).reduce(\n            (\n                output_entries: Record<string, any[]>,\n                [node_id, node]: [string, any]\n            ) => {\n                if (store.data.object_info[node.class_type].output_node) {\n                    output_entries[node_id] = []\n                }\n                return output_entries\n            },\n            {}\n        )\n\n        //slider variables for output nodes\n        //TODO: delete store.data.output_thumbnail_image_size before loading a new workflow\n        for (let key in toJS(store.data.current_prompt2_output)) {\n            store.data.output_thumbnail_image_size[key] = 200\n        }\n\n        const workflow_name = store.data.selected_workflow_name\n        if (workflow_name) {\n            // check if the workflow has a name\n\n            if (workflow_name in storage.localStorage) {\n                //load the workflow data from local storage\n                //1) load the last parameters used in generation\n                //2) load the order of the nodes\n                //3) load the labels of the nodes\n\n                const workflow_data: WorkflowData =\n                    loadWorkflowData(workflow_name)\n                if (\n                    util.isSameStructure(\n                        workflow_data.prompt,\n                        toJS(store.data.current_prompt2)\n                    )\n                ) {\n                    //load 1)\n                    store.data.current_prompt2 = workflow_data.prompt\n                    //load 2)\n                    store.data.nodes_order = workflow_data.nodes_order\n                    //load 3)\n                    store.data.nodes_label = workflow_data.nodes_label\n                } else {\n                    // do not load. instead override the localStorage with the new values\n                    workflow_data.prompt = toJS(store.data.current_prompt2)\n                    workflow_data.nodes_order = toJS(store.data.nodes_order)\n                    workflow_data.nodes_label = toJS(store.data.nodes_label)\n\n                    saveWorkflowData(workflow_name, workflow_data)\n                }\n            } else {\n                // if workflow data is missing from local storage then save it for next time.\n                //1) save parameters values\n                //2) save nodes order\n                //3) save nodes label\n\n                const prompt = toJS(store.data.current_prompt2)\n                const nodes_order = toJS(store.data.nodes_order)\n                const nodes_label = toJS(store.data.nodes_label)\n                saveWorkflowData(workflow_name, {\n                    prompt,\n                    nodes_order,\n                    nodes_label,\n                })\n            }\n        }\n    } catch (e) {\n        console.error(e)\n        app.showAlert(`${e}`)\n    }\n}\n\nasync function getUploadedImages(images_list: string[]) {\n    //convert all of comfyui loaded images into base64url that the plugin can use\n    let uploaded_images = images_list\n\n    uploaded_images = uploaded_images.filter((image_name: string) => {\n        let extension = image_name.split('.').pop() || ''\n        // return extension !== 'gif' && extension !== 'mp4'\n        return ['png', 'jpg', 'webp'].includes(extension)\n    })\n\n    const uploaded_images_base64_url: string[] = await Promise.all(\n        uploaded_images.map(async (filename: string) => {\n            try {\n                return await util.base64UrlFromComfy({\n                    filename: encodeURIComponent(filename),\n                    type: 'input',\n                    subfolder: 'Auto-Photoshop-SD',\n                })\n            } catch (e) {\n                console.warn(e)\n                return ''\n            }\n        })\n    )\n    store.data.uploaded_images_list =\n        store.data.object_info.LoadImage.input.required['image'][0]\n\n    store.data.uploaded_images_base64_url = uploaded_images_base64_url\n    return store.data.uploaded_images_base64_url\n}\n\nfunction getBorderColor(is_output: boolean, last_moved: boolean) {\n    let color: string | undefined = void 0\n    if (last_moved) {\n        // color = '#2c4639'\n        color = '#e34d12'\n\n        return color\n    }\n    if (is_output) {\n        // color = '#e34d12'\n        color = '#6db579'\n    } else {\n        color = '#6d6c6c'\n    }\n\n    return color\n}\n@observer\nclass ComfyWorkflowComponent extends React.Component<{}, { value?: number }> {\n    async componentDidMount(): Promise<void> {\n        try {\n            store.data.object_info = await comfyapi.comfy_api.init()\n            // getUploadedImages(\n            //     store.data.object_info.LoadImage.input.required['image'][0]\n            // )\n            if (store.data.object_info?.VHS_LoadVideo) {\n                store.data.uploaded_video_list =\n                    store.data.object_info.VHS_LoadVideo.input.required[\n                        'video'\n                    ][0]\n            }\n        } catch (e) {\n            console.error(e)\n        }\n    }\n\n    render(): React.ReactNode {\n        return (\n            <div>\n                <div\n                    style={{ display: 'flex', justifyContent: 'space-between' }}\n                >\n                    {/* {util.getNodes(util.hi_res_workflow).map((node, index) => {\n                    // return <div>{node.class_type}</div>\n                    return (\n                        <div key={'node_' + index}>{this.renderNode(node)}</div>\n                    )\n                })} */}\n                    <button\n                        className=\"btnSquare\"\n                        style={{\n                            display: store.data.can_generate ? void 0 : 'none',\n                        }}\n                        onClick={async () => {\n                            // let interval\n                            store.data.can_generate = false\n                            let interval: NodeJS.Timeout = setInterval(\n                                function () {\n                                    store.data.progress_value++\n                                    console.log(store.data.progress_value)\n                                },\n                                1000\n                            ) // 1000 milliseconds = 1 second\n                            try {\n                                // Start the progress update\n\n                                util.runRandomSeedScript()\n                                let { outputs, separated_outputs } =\n                                    await util.postPromptAndGetBase64JsonResult(\n                                        toJS(store.data.current_prompt2)\n                                    )\n                                store.data.current_prompt2_output =\n                                    outputs ?? {}\n                            } catch (e) {\n                                console.error(e)\n                            } finally {\n                                clearInterval(interval as NodeJS.Timeout)\n                                store.data.progress_value = 0\n                                store.data.can_generate = true\n                            }\n                        }}\n                    >\n                        Generate\n                    </button>\n                    <button\n                        className=\"btnSquare\"\n                        style={{\n                            display: store.data.can_generate ? void 0 : 'none',\n                        }}\n                        onClick={async () => {\n                            store.data.infinite_loop = true\n\n                            async function infiniteCanvasImageScript() {\n                                try {\n                                    let numOfImagesToSync = 0\n                                    // for (const node_id in store.data\n                                    //     .sync_from_canvas) {\n                                    for (const node_id in store.data\n                                        .loadImage_loading_method) {\n                                        if (\n                                            // store.data.sync_from_canvas[node_id]\n                                            store.data.loadImage_loading_method[\n                                                node_id\n                                            ].method ===\n                                            'Sync From Whole Canvas'\n                                        ) {\n                                            numOfImagesToSync += 1\n                                        }\n                                    }\n\n                                    if (numOfImagesToSync === 0) {\n                                        // return undefined\n                                        //\n                                    } else {\n                                        //debounce if the function executed recently\n                                        const now = Date.now()\n                                        if (now - store.data.lastCall < 2000) {\n                                            console.log(\n                                                'getImageFromCanvas debounced'\n                                            )\n                                            // return undefined\n                                        } else {\n                                            store.data.lastCall = now\n\n                                            const image_data_url =\n                                                await getImageFromCanvas_new()\n\n                                            const image_base64 =\n                                                base64UrlToBase64(\n                                                    image_data_url!\n                                                )\n\n                                            const image_name =\n                                                await reuseOrUploadComfyImage(\n                                                    image_base64,\n                                                    store.data\n                                                        .base64_to_uploaded_images_names,\n                                                    'input'\n                                                )\n                                            if (image_name) {\n                                                for (const node_id of Object.keys(\n                                                    // store.data.sync_from_canvas\n                                                    store.data\n                                                        .loadImage_loading_method\n                                                )) {\n                                                    if (\n                                                        store.data\n                                                            .loadImage_loading_method[\n                                                            node_id\n                                                        ].method ===\n                                                        'Sync From Whole Canvas'\n                                                    ) {\n                                                        await onChangeLoadImage(\n                                                            node_id,\n                                                            image_name,\n                                                            'input'\n                                                        )\n                                                    }\n                                                }\n                                            }\n                                        }\n                                    }\n\n                                    // sync from layer\n\n                                    for (const node_id in store.data\n                                        .loadImage_loading_method) {\n                                        try {\n                                            if (\n                                                store.data\n                                                    .loadImage_loading_method[\n                                                    node_id\n                                                ].method === 'Sync From a Layer'\n                                            ) {\n                                                const layer_id =\n                                                    store.data\n                                                        .loadImage_loading_method[\n                                                        node_id\n                                                    ].data?.layer_id\n                                                const layer_data_url =\n                                                    await getImageFromCanvas_new(\n                                                        layer_id!\n                                                    )\n                                                const layer_image_base64 =\n                                                    base64UrlToBase64(\n                                                        layer_data_url!\n                                                    )\n\n                                                const image_name =\n                                                    await reuseOrUploadComfyImage(\n                                                        layer_image_base64,\n                                                        store.data\n                                                            .base64_to_uploaded_images_names,\n                                                        'input'\n                                                    )\n                                                if (image_name) {\n                                                    await onChangeLoadImage(\n                                                        node_id,\n                                                        image_name,\n                                                        'input'\n                                                    )\n                                                }\n                                            }\n                                        } catch (e) {\n                                            console.error(e)\n                                            if (!isValidVersion(25)) {\n                                                // const errorMessage = `Real-time img2img Require Adobe Photoshop version 25 or higher. Your current version is ${host.version}. Please update Adobe Photoshop to use this feature. You can still use realtime txt2img.`\n                                                // app.showAlert(errorMessage)\n                                                throw e\n                                            }\n                                        }\n                                    }\n                                } catch (e) {\n                                    console.error(e)\n                                    if (!isValidVersion(25)) {\n                                        const errorMessage = `Real-time img2img Require Adobe Photoshop version 25 or higher. Your current version is ${host.version}. Please update Adobe Photoshop to use this feature. You can still use realtime txt2img.`\n                                        app.showAlert(errorMessage)\n                                        throw errorMessage\n                                    }\n                                    throw e\n                                }\n                            }\n                            while (store.data.infinite_loop) {\n                                store.data.can_generate = false\n                                let interval: NodeJS.Timeout = setInterval(\n                                    function () {\n                                        store.data.progress_value++\n                                        console.log(store.data.progress_value)\n                                    },\n                                    1000\n                                ) // 1000 milliseconds = 1 second\n\n                                try {\n                                    // Start the progress update\n\n                                    util.runRandomSeedScript()\n                                    await infiniteCanvasImageScript()\n\n                                    let { outputs, separated_outputs } =\n                                        await util.postPromptAndGetBase64JsonResult(\n                                            toJS(store.data.current_prompt2)\n                                        )\n                                    store.data.current_prompt2_output =\n                                        outputs ?? {}\n                                } catch (e) {\n                                    console.error(e)\n                                    break\n                                } finally {\n                                    clearInterval(interval as NodeJS.Timeout)\n                                    store.data.progress_value = 0\n                                    store.data.can_generate = true\n                                }\n                            }\n                        }}\n                    >\n                        Generate RealTime\n                    </button>\n                    <button\n                        className=\"btnSquare\"\n                        style={{\n                            display: !store.data.can_generate ? void 0 : 'none',\n                        }}\n                        onClick={async () => {\n                            await comfyapi.comfy_api.interrupt()\n                            store.data.infinite_loop = false\n                        }}\n                    >\n                        Interrupt\n                    </button>\n                    <button\n                        className=\"btnSquare\"\n                        style={{\n                            display: store.data.can_edit_nodes\n                                ? void 0\n                                : 'none',\n                        }}\n                        onClick={async () => {\n                            resetWorkflowData(store.data.selected_workflow_name)\n                        }}\n                    >\n                        Reset Workflow\n                    </button>\n                    <button\n                        className=\"btnSquare\"\n                        onClick={async () => {\n                            store.data.last_moved = void 0\n                            store.data.can_edit_nodes =\n                                !store.data.can_edit_nodes\n\n                            const workflow_name =\n                                store.data.selected_workflow_name\n                            const prompt = toJS(store.data.current_prompt2)\n                            const nodes_order = toJS(store.data.nodes_order)\n                            const nodes_label = toJS(store.data.nodes_label)\n\n                            saveWorkflowData(workflow_name, {\n                                prompt,\n                                nodes_order,\n                                nodes_label,\n                            })\n                        }}\n                    >\n                        {store.data.can_edit_nodes\n                            ? 'Done Editing'\n                            : 'Edit Nodes'}\n                    </button>\n                </div>\n                <div>\n                    <sp-progressbar\n                        class=\"pProgressBars preview_progress_bar\"\n                        max=\"100\"\n                        value={`${store.data.progress_value}`}\n                    ></sp-progressbar>\n                </div>\n                <div>\n                    <SpMenu\n                        size=\"m\"\n                        title=\"workflows\"\n                        items={Object.keys(store.data.workflows2)}\n                        label_item=\"Select a workflow\"\n                        selected_index={Object.values(\n                            store.data.workflows2\n                        ).indexOf(store.data.selected_workflow_name)}\n                        onChange={async (id: any, value: any) => {\n                            store.data.selected_workflow_name = value.item\n                            loadWorkflow2(store.data.workflows2[value.item])\n                        }}\n                    ></SpMenu>{' '}\n                    <button\n                        className=\"btnSquare refreshButton btnResetSettings\"\n                        title=\"reload the current workflow\"\n                        onClick={async () => {\n                            store.data.object_info =\n                                await comfyapi.comfy_api.init(true)\n\n                            store.data.current_prompt2 = {}\n\n                            setTimeout(() => {\n                                loadWorkflow2(\n                                    toJS(\n                                        store.data.workflows2[\n                                            store.data.selected_workflow_name\n                                        ]\n                                    )\n                                )\n                            }, 250)\n                        }}\n                    ></button>\n                    <button\n                        className=\"btnSquare\"\n                        style={{ marginLeft: '3px' }}\n                        onClick={async () => {\n                            try {\n                                const entries = await workflowEntries()\n\n                                if (entries.length > 0) {\n                                    store.data.user_custom_workflow = {}\n                                    for (const entry of entries) {\n                                        const json = JSON.parse(\n                                            await entry.read({\n                                                format: storage.formats.utf8,\n                                            })\n                                        )\n                                        const workflow_name =\n                                            entry.name.split('.json')[0]\n                                        store.data.user_custom_workflow[\n                                            workflow_name\n                                        ] = json\n                                    }\n\n                                    store.data.workflows2 = {\n                                        ...store.data.workflows2,\n                                        ...store.data.user_custom_workflow,\n                                    }\n                                }\n                            } catch (e) {\n                                console.error(e)\n                            }\n                        }}\n                    >\n                        Load\n                    </button>\n                </div>\n\n                {store.data.object_info ? (\n                    <>\n                        <div>\n                            {util\n                                .getNodes(store.data.current_prompt2)\n                                .sort(\n                                    ([node_id1, node1], [node_id2, node2]) => {\n                                        return (\n                                            store.data.nodes_order.indexOf(\n                                                node_id1\n                                            ) -\n                                            store.data.nodes_order.indexOf(\n                                                node_id2\n                                            )\n                                        )\n                                    }\n                                )\n\n                                .map(([node_id, node], index) => {\n                                    try {\n                                        const is_output =\n                                            store.data.object_info[\n                                                node.class_type\n                                            ].output_node\n                                        return (\n                                            <div\n                                                key={`node_${node_id}_${index}`}\n                                                style={{\n                                                    border: '2px solid #6d6c6c',\n                                                    borderColor: getBorderColor(\n                                                        is_output,\n                                                        store.data\n                                                            .last_moved ===\n                                                            node_id\n                                                    ),\n\n                                                    padding: '3px',\n                                                }}\n                                            >\n                                                <div\n                                                    style={{\n                                                        display: store.data\n                                                            .can_edit_nodes\n                                                            ? 'flex'\n                                                            : 'none',\n                                                        flexDirection: 'row',\n                                                        justifyContent:\n                                                            'space-between',\n                                                    }}\n                                                >\n                                                    <div\n                                                        style={{\n                                                            display: 'flex',\n                                                            flexDirection:\n                                                                'column',\n                                                            alignItems:\n                                                                'flex-start',\n                                                        }}\n                                                    >\n                                                        <button\n                                                            id={`${node_id}_new_button_1`}\n                                                            style={{\n                                                                width: '26px',\n                                                            }}\n                                                            title={\n                                                                'move node to the first position'\n                                                            }\n                                                            className=\"btnSquare\"\n                                                            onClick={(\n                                                                e: any\n                                                            ) => {\n                                                                store.data.last_moved =\n                                                                    node_id\n                                                                moveToTop(index)\n                                                            }}\n                                                        >\n                                                            {' '}\n                                                            {'▲▲'}{' '}\n                                                        </button>\n                                                        <button\n                                                            id={`${node_id}_new_button_2`}\n                                                            style={{\n                                                                width: '26px',\n                                                            }}\n                                                            title={\n                                                                'move node to the last position'\n                                                            }\n                                                            className=\"btnSquare\"\n                                                            onClick={() => {\n                                                                store.data.last_moved =\n                                                                    node_id\n                                                                moveToBottom(\n                                                                    index\n                                                                )\n                                                            }}\n                                                        >\n                                                            {' '}\n                                                            {'▼▼'}{' '}\n                                                        </button>\n                                                    </div>\n                                                    <div\n                                                        style={{\n                                                            display: 'flex',\n                                                            flexDirection:\n                                                                'column',\n                                                            alignItems:\n                                                                'flex-end',\n                                                        }}\n                                                    >\n                                                        <button\n                                                            id={`${node_id}_swap_up`}\n                                                            style={{\n                                                                width: '26px',\n                                                            }}\n                                                            className=\"btnSquare\"\n                                                            onClick={(\n                                                                e: any\n                                                            ) => {\n                                                                store.data.last_moved =\n                                                                    node_id\n                                                                console.log(\n                                                                    'node_id assign to the swap button: ',\n                                                                    node_id\n                                                                )\n                                                                swap(\n                                                                    index,\n                                                                    index - 1\n                                                                )\n                                                            }}\n                                                        >\n                                                            {' '}\n                                                            {'▲'}{' '}\n                                                        </button>\n                                                        <button\n                                                            id={`${node_id}_swap_down`}\n                                                            style={{\n                                                                width: '26px',\n                                                            }}\n                                                            className=\"btnSquare\"\n                                                            onClick={() => {\n                                                                store.data.last_moved =\n                                                                    node_id\n                                                                swap(\n                                                                    index,\n                                                                    index + 1\n                                                                )\n                                                            }}\n                                                        >\n                                                            {' '}\n                                                            {'▼'}{' '}\n                                                        </button>\n                                                    </div>\n                                                </div>\n                                                <sp-label>\n                                                    \"{node_id}\":{' '}\n                                                    <span\n                                                        style={{\n                                                            color: store.data\n                                                                .can_edit_nodes\n                                                                ? 'white'\n                                                                : void 0,\n                                                        }}\n                                                    >\n                                                        {\n                                                            store.data\n                                                                .nodes_label[\n                                                                node_id\n                                                            ]\n                                                        }\n                                                    </span>{' '}\n                                                </sp-label>{' '}\n                                                <sp-label\n                                                    style={{\n                                                        display: store.data\n                                                            .can_edit_nodes\n                                                            ? void 0\n                                                            : 'none',\n                                                    }}\n                                                >\n                                                    {node.class_type}\n                                                </sp-label>\n                                                <div\n                                                    style={{\n                                                        display: !store.data\n                                                            .can_edit_nodes\n                                                            ? 'none'\n                                                            : void 0,\n                                                    }}\n                                                >\n                                                    <sp-textfield\n                                                        type=\"text\"\n                                                        placeholder=\"write a node label\"\n                                                        value={\n                                                            store.data\n                                                                .nodes_label[\n                                                                node_id\n                                                            ]\n                                                        }\n                                                        onInput={(\n                                                            event: any\n                                                        ) => {\n                                                            store.data.nodes_label[\n                                                                node_id\n                                                            ] =\n                                                                event.target.value\n                                                        }}\n                                                    ></sp-textfield>\n                                                </div>\n                                                {renderNode(\n                                                    node_id,\n                                                    node,\n                                                    is_output\n                                                )}\n                                            </div>\n                                        )\n                                    } catch (e) {\n                                        console.error(\n                                            `node_id: ${node_id}`,\n                                            'node:',\n                                            toJS(node),\n                                            'node.class_type',\n                                            node.class_type,\n                                            'store.data.object_info[node.class_type]: ',\n                                            store.data.object_info[\n                                                node.class_type\n                                            ],\n                                            'error: ',\n                                            e\n                                        )\n                                        return (\n                                            <sp-label\n                                                id=\"\"\n                                                style={{\n                                                    color: '#ff595e',\n                                                    whiteSpace: 'normal',\n                                                }}\n                                            >\n                                                {Locale(\n                                                    `Error: Node ${node.class_type} is\n                                                missing, please install it from\n                                                comfyui manager`\n                                                )}\n                                            </sp-label>\n                                        )\n                                    }\n                                })}\n                        </div>\n                    </>\n                ) : (\n                    void 0\n                )}\n            </div>\n        )\n    }\n}\nconst container = document.getElementById('ComfyUIContainer')!\nconst root = ReactDOM.createRoot(container)\nroot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n            <Collapsible\n                defaultIsOpen={true}\n                label={Locale('Custom ComfyUI Workflow')}\n            >\n                {/* <ComfyNodeComponent></ComfyNodeComponent> */}\n\n                <ComfyWorkflowComponent />\n            </Collapsible>\n        </div>\n        {/* <ComfyNodeComponent></ComfyNodeComponent> */}\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/comfyui/img2img_api.json",
    "content": "{\n  \"3\": {\n    \"inputs\": {\n      \"seed\": 532429388244110,\n      \"steps\": 20,\n      \"cfg\": 8,\n      \"sampler_name\": \"dpmpp_sde\",\n      \"scheduler\": \"karras\",\n      \"denoise\": 0.72,\n      \"model\": [\n        \"76\",\n        0\n      ],\n      \"positive\": [\n        \"91\",\n        3\n      ],\n      \"negative\": [\n        \"91\",\n        4\n      ],\n      \"latent_image\": [\n        \"63\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"text\": [\n        \"76\",\n        2\n      ],\n      \"clip\": [\n        \"76\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"text\": [\n        \"78\",\n        2\n      ],\n      \"clip\": [\n        \"78\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"8\": {\n    \"inputs\": {\n      \"samples\": [\n        \"3\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"9\": {\n    \"inputs\": {\n      \"filename_prefix\": \"ComfyUI\",\n      \"images\": [\n        \"8\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"11\": {\n    \"inputs\": {\n      \"seed\": 4820153955672,\n      \"steps\": 20,\n      \"cfg\": 8,\n      \"sampler_name\": \"dpmpp_2m\",\n      \"scheduler\": \"simple\",\n      \"denoise\": 0.4,\n      \"model\": [\n        \"76\",\n        0\n      ],\n      \"positive\": [\n        \"91\",\n        3\n      ],\n      \"negative\": [\n        \"91\",\n        4\n      ],\n      \"latent_image\": [\n        \"55\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"12\": {\n    \"inputs\": {\n      \"filename_prefix\": \"ComfyUI\",\n      \"images\": [\n        \"13\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"13\": {\n    \"inputs\": {\n      \"samples\": [\n        \"11\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"16\": {\n    \"inputs\": {\n      \"ckpt_name\": \"dreamshaper_8.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"55\": {\n    \"inputs\": {\n      \"upscale_method\": \"nearest-exact\",\n      \"scale_by\": 2,\n      \"samples\": [\n        \"3\",\n        0\n      ]\n    },\n    \"class_type\": \"LatentUpscaleBy\"\n  },\n  \"57\": {\n    \"inputs\": {\n      \"vae_name\": \"MoistMix.vae.pt\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"58\": {\n    \"inputs\": {\n      \"image\": \"Layer 3 (1).png\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"59\": {\n    \"inputs\": {\n      \"pixels\": [\n        \"60\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEEncode\"\n  },\n  \"60\": {\n    \"inputs\": {\n      \"upscale_method\": \"nearest-exact\",\n      \"width\": 512,\n      \"height\": 512,\n      \"crop\": \"disabled\",\n      \"image\": [\n        \"58\",\n        0\n      ]\n    },\n    \"class_type\": \"ImageScale\"\n  },\n  \"63\": {\n    \"inputs\": {\n      \"amount\": 1,\n      \"samples\": [\n        \"59\",\n        0\n      ]\n    },\n    \"class_type\": \"RepeatLatentBatch\"\n  },\n  \"76\": {\n    \"inputs\": {\n      \"prompt\": \"\",\n      \"model\": [\n        \"78\",\n        0\n      ],\n      \"clip\": [\n        \"109\",\n        0\n      ]\n    },\n    \"class_type\": \"LoadLorasFromPrompt\"\n  },\n  \"78\": {\n    \"inputs\": {\n      \"prompt\": \"bad hands, text, watermark\",\n      \"model\": [\n        \"16\",\n        0\n      ],\n      \"clip\": [\n        \"109\",\n        0\n      ]\n    },\n    \"class_type\": \"LoadLorasFromPrompt\"\n  },\n  \"88\": {\n    \"inputs\": {\n      \"images\": [\n        \"91\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"89\": {\n    \"inputs\": {\n      \"images\": [\n        \"91\",\n        1\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"90\": {\n    \"inputs\": {\n      \"images\": [\n        \"91\",\n        2\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"91\": {\n    \"inputs\": {\n      \"is_enabled_1\": \"disable\",\n      \"preprocessor_name_1\": \"CannyEdgePreprocessor\",\n      \"control_net_name_1\": \"control_lora_rank128_v11p_sd15_canny_fp16.safetensors\",\n      \"strength_1\": 1,\n      \"threshold_a_1\": 100,\n      \"threshold_b_1\": 200,\n      \"start_percent_1\": 0,\n      \"end_percent_1\": 1,\n      \"resolution_1\": 512,\n      \"is_enabled_2\": \"disable\",\n      \"preprocessor_name_2\": \"OpenposePreprocessor\",\n      \"control_net_name_2\": \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n      \"strength_2\": 1,\n      \"threshold_a_2\": 0,\n      \"threshold_b_2\": 0,\n      \"start_percent_2\": 0,\n      \"end_percent_2\": 1,\n      \"resolution_2\": 512,\n      \"is_enabled_3\": \"disable\",\n      \"preprocessor_name_3\": \"InpaintPreprocessor\",\n      \"control_net_name_3\": \"control_lora_rank128_v11p_sd15_inpaint_fp16.safetensors\",\n      \"strength_3\": 1,\n      \"threshold_a_3\": 0,\n      \"threshold_b_3\": 0,\n      \"start_percent_3\": 0,\n      \"end_percent_3\": 1,\n      \"resolution_3\": 512,\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"7\",\n        0\n      ]\n    },\n    \"class_type\": \"ControlNetScript\"\n  },\n  \"109\": {\n    \"inputs\": {\n      \"stop_at_clip_layer\": -1,\n      \"clip\": [\n        \"16\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPSetLastLayer\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/img2img_workflow.json",
    "content": "{\n  \"last_node_id\": 109,\n  \"last_link_id\": 204,\n  \"nodes\": [\n    {\n      \"id\": 8,\n      \"type\": \"VAEDecode\",\n      \"pos\": [\n        1238.8565730529783,\n        603.497425166778\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 32,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 36\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 82\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            9\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEDecode\"\n      }\n    },\n    {\n      \"id\": 13,\n      \"type\": \"VAEDecode\",\n      \"pos\": [\n        1961,\n        125\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 36,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 15\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 83\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            17\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEDecode\"\n      }\n    },\n    {\n      \"id\": 66,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        210,\n        188\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 21,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 134\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            100\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 57,\n      \"type\": \"VAELoader\",\n      \"pos\": [\n        -194,\n        692\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 0,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            142\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Load VAE | id:vae\",\n      \"properties\": {\n        \"Node name for S&R\": \"VAELoader\"\n      },\n      \"widgets_values\": [\n        \"MoistMix.vae.pt\"\n      ]\n    },\n    {\n      \"id\": 56,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        247,\n        639\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 11,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 142\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            82,\n            83,\n            85\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 65,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        237,\n        92\n      ],\n      \"size\": [\n        82,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 20,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 133\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            94,\n            95\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 78,\n      \"type\": \"LoadLorasFromPrompt\",\n      \"pos\": [\n        -261,\n        422\n      ],\n      \"size\": {\n        \"0\": 462,\n        \"1\": 200\n      },\n      \"flags\": {},\n      \"order\": 17,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 193\n        },\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 204\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            140\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            138\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"STRING\",\n          \"type\": \"STRING\",\n          \"links\": [\n            137\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Loras From Prompt | id:multi_loras_negative_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadLorasFromPrompt\"\n      },\n      \"widgets_values\": [\n        \"bad hands, text, watermark\"\n      ]\n    },\n    {\n      \"id\": 11,\n      \"type\": \"KSampler\",\n      \"pos\": [\n        1587.0000488281248,\n        125.99995765686035\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 262\n      },\n      \"flags\": {},\n      \"order\": 35,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 95,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 153,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 155,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"latent_image\",\n          \"type\": \"LATENT\",\n          \"link\": 79,\n          \"slot_index\": 3\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            15\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"KSampler | id:hires_sampler\",\n      \"properties\": {\n        \"Node name for S&R\": \"KSampler\"\n      },\n      \"widgets_values\": [\n        4820153955672,\n        \"fixed\",\n        20,\n        8,\n        \"dpmpp_2m\",\n        \"simple\",\n        0.4\n      ]\n    },\n    {\n      \"id\": 85,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        604,\n        -327\n      ],\n      \"size\": [\n        140.8,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 30,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 199,\n          \"slot_index\": 0\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            153,\n            154\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 7,\n      \"type\": \"CLIPTextEncode\",\n      \"pos\": [\n        638.8565730529789,\n        359.49742516677856\n      ],\n      \"size\": {\n        \"0\": 425.27801513671875,\n        \"1\": 180.6060791015625\n      },\n      \"flags\": {},\n      \"order\": 19,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 138\n        },\n        {\n          \"name\": \"text\",\n          \"type\": \"STRING\",\n          \"link\": 137,\n          \"widget\": {\n            \"name\": \"text\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            171\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Text Encode (Prompt) | id:negative_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPTextEncode\"\n      },\n      \"widgets_values\": [\n        \"bad hands, text, watermark\\n\"\n      ]\n    },\n    {\n      \"id\": 86,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        612,\n        -277\n      ],\n      \"size\": [\n        140.8,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 29,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 174,\n          \"slot_index\": 0\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            155,\n            156\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 55,\n      \"type\": \"LatentUpscaleBy\",\n      \"pos\": [\n        1465,\n        -133\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 82\n      },\n      \"flags\": {},\n      \"order\": 33,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 78\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            79\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Upscale Latent By | id:scaler\",\n      \"properties\": {\n        \"Node name for S&R\": \"LatentUpscaleBy\"\n      },\n      \"widgets_values\": [\n        \"nearest-exact\",\n        2\n      ]\n    },\n    {\n      \"id\": 93,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -1630,\n        -1670\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 314\n      },\n      \"flags\": {},\n      \"order\": 1,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            167\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_mask_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 95,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -1690,\n        -1230\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 314\n      },\n      \"flags\": {},\n      \"order\": 2,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            169\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_mask_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 6,\n      \"type\": \"CLIPTextEncode\",\n      \"pos\": [\n        637,\n        123\n      ],\n      \"size\": {\n        \"0\": 422.84503173828125,\n        \"1\": 164.31304931640625\n      },\n      \"flags\": {},\n      \"order\": 22,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 100\n        },\n        {\n          \"name\": \"text\",\n          \"type\": \"STRING\",\n          \"link\": 135,\n          \"widget\": {\n            \"name\": \"text\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            196\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Text Encode (Prompt) | id:positive_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPTextEncode\"\n      },\n      \"widgets_values\": [\n        \"lora_bright_style girl\"\n      ]\n    },\n    {\n      \"id\": 63,\n      \"type\": \"RepeatLatentBatch\",\n      \"pos\": [\n        800,\n        -413\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 16,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 200\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            92\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Repeat Latent Batch | id:latent_batch\",\n      \"properties\": {\n        \"Node name for S&R\": \"RepeatLatentBatch\"\n      },\n      \"widgets_values\": [\n        1\n      ]\n    },\n    {\n      \"id\": 106,\n      \"type\": \"unCLIPConditioning\",\n      \"pos\": [\n        -1619,\n        -720\n      ],\n      \"size\": {\n        \"0\": 393,\n        \"1\": 102\n      },\n      \"flags\": {},\n      \"order\": 23,\n      \"mode\": 4,\n      \"inputs\": [\n        {\n          \"name\": \"conditioning\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 196,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"clip_vision_output\",\n          \"type\": \"CLIP_VISION_OUTPUT\",\n          \"link\": 194\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            195\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"unCLIPConditioning\"\n      },\n      \"widgets_values\": [\n        1,\n        0\n      ]\n    },\n    {\n      \"id\": 9,\n      \"type\": \"SaveImage\",\n      \"pos\": [\n        1495,\n        584\n      ],\n      \"size\": {\n        \"0\": 232.94032287597656,\n        \"1\": 282.4336242675781\n      },\n      \"flags\": {},\n      \"order\": 34,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 9\n        }\n      ],\n      \"properties\": {},\n      \"widgets_values\": [\n        \"ComfyUI\"\n      ]\n    },\n    {\n      \"id\": 107,\n      \"type\": \"unCLIPConditioning\",\n      \"pos\": [\n        -283,\n        -852\n      ],\n      \"size\": {\n        \"0\": 393,\n        \"1\": 102\n      },\n      \"flags\": {},\n      \"order\": 28,\n      \"mode\": 4,\n      \"inputs\": [\n        {\n          \"name\": \"conditioning\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 198,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"clip_vision_output\",\n          \"type\": \"CLIP_VISION_OUTPUT\",\n          \"link\": 197,\n          \"slot_index\": 1\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            199\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"unCLIPConditioning\"\n      },\n      \"widgets_values\": [\n        1,\n        0\n      ]\n    },\n    {\n      \"id\": 104,\n      \"type\": \"IPAdapter\",\n      \"pos\": [\n        -503,\n        -288\n      ],\n      \"size\": {\n        \"0\": 380.4000244140625,\n        \"1\": 166\n      },\n      \"flags\": {},\n      \"order\": 15,\n      \"mode\": 4,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 192,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"image\",\n          \"type\": \"IMAGE\",\n          \"link\": 190\n        },\n        {\n          \"name\": \"clip_vision\",\n          \"type\": \"CLIP_VISION\",\n          \"link\": 191,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"mask\",\n          \"type\": \"MASK\",\n          \"link\": null\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            193\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP_VISION_OUTPUT\",\n          \"type\": \"CLIP_VISION_OUTPUT\",\n          \"links\": [\n            194,\n            197\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"IPAdapter\"\n      },\n      \"widgets_values\": [\n        1,\n        \"ip-adapter-plus_sd15.bin\",\n        \"fp16\"\n      ]\n    },\n    {\n      \"id\": 105,\n      \"type\": \"CLIPVisionLoader\",\n      \"pos\": [\n        -923,\n        -242\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 3,\n      \"mode\": 4,\n      \"outputs\": [\n        {\n          \"name\": \"CLIP_VISION\",\n          \"type\": \"CLIP_VISION\",\n          \"links\": [\n            191\n          ],\n          \"shape\": 3\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPVisionLoader\"\n      },\n      \"widgets_values\": [\n        \"model.safetensors\"\n      ]\n    },\n    {\n      \"id\": 60,\n      \"type\": \"ImageScale\",\n      \"pos\": [\n        -554,\n        -43\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 130\n      },\n      \"flags\": {},\n      \"order\": 12,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"image\",\n          \"type\": \"IMAGE\",\n          \"link\": 86\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            87,\n            190\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Upscale Image | id:init_image_scale\",\n      \"properties\": {\n        \"Node name for S&R\": \"ImageScale\"\n      },\n      \"widgets_values\": [\n        \"nearest-exact\",\n        512,\n        512,\n        \"disabled\"\n      ]\n    },\n    {\n      \"id\": 59,\n      \"type\": \"VAEEncode\",\n      \"pos\": [\n        523,\n        -531\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 14,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"pixels\",\n          \"type\": \"IMAGE\",\n          \"link\": 87\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 85\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            200\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEEncode\"\n      }\n    },\n    {\n      \"id\": 103,\n      \"type\": \"EmptyLatentImage\",\n      \"pos\": [\n        514,\n        -716\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 106\n      },\n      \"flags\": {},\n      \"order\": 4,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"EmptyLatentImage\"\n      },\n      \"widgets_values\": [\n        512,\n        512,\n        1\n      ]\n    },\n    {\n      \"id\": 3,\n      \"type\": \"KSampler\",\n      \"pos\": [\n        928,\n        -292\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 262\n      },\n      \"flags\": {},\n      \"order\": 31,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 94\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 154\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 156\n        },\n        {\n          \"name\": \"latent_image\",\n          \"type\": \"LATENT\",\n          \"link\": 92\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            36,\n            78\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"KSampler | id:sampler\",\n      \"properties\": {\n        \"Node name for S&R\": \"KSampler\"\n      },\n      \"widgets_values\": [\n        532429388244110,\n        \"fixed\",\n        20,\n        8,\n        \"dpmpp_sde\",\n        \"karras\",\n        0.72\n      ]\n    },\n    {\n      \"id\": 92,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -1960,\n        -2190\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 314\n      },\n      \"flags\": {\n        \"collapsed\": false\n      },\n      \"order\": 5,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            165\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_mask_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 58,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -1328,\n        -135\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 314\n      },\n      \"flags\": {},\n      \"order\": 6,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            86\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:init_image\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"Layer 3 (1).png\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 89,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        -280,\n        -1260\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 26,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 162\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 90,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        -40,\n        -1260\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 27,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 163\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 88,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        -530,\n        -1260\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 25,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 161\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 12,\n      \"type\": \"SaveImage\",\n      \"pos\": [\n        2367,\n        49\n      ],\n      \"size\": {\n        \"0\": 407.53717041015625,\n        \"1\": 468.13226318359375\n      },\n      \"flags\": {},\n      \"order\": 37,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 17\n        }\n      ],\n      \"title\": \"Save Image | id:hires_output\",\n      \"properties\": {},\n      \"widgets_values\": [\n        \"ComfyUI\"\n      ]\n    },\n    {\n      \"id\": 91,\n      \"type\": \"ControlNetScript\",\n      \"pos\": [\n        -1381,\n        -1042\n      ],\n      \"size\": {\n        \"0\": 506.0240173339844,\n        \"1\": 822\n      },\n      \"flags\": {},\n      \"order\": 24,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 195\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 171,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"image_1\",\n          \"type\": \"IMAGE\",\n          \"link\": 201\n        },\n        {\n          \"name\": \"mask_1\",\n          \"type\": \"IMAGE\",\n          \"link\": 165,\n          \"slot_index\": 3\n        },\n        {\n          \"name\": \"image_2\",\n          \"type\": \"IMAGE\",\n          \"link\": 166\n        },\n        {\n          \"name\": \"mask_2\",\n          \"type\": \"IMAGE\",\n          \"link\": 167\n        },\n        {\n          \"name\": \"image_3\",\n          \"type\": \"IMAGE\",\n          \"link\": 168\n        },\n        {\n          \"name\": \"mask_3\",\n          \"type\": \"IMAGE\",\n          \"link\": 169\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"preprocessed_image_1\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            161\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"preprocessed_image_2\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            162\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"preprocessed_image_3\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            163\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            198\n          ],\n          \"shape\": 3,\n          \"slot_index\": 3\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            174\n          ],\n          \"shape\": 3,\n          \"slot_index\": 4\n        }\n      ],\n      \"title\": \"ControlNet Script | id:controlnet_script\",\n      \"properties\": {\n        \"Node name for S&R\": \"ControlNetScript\"\n      },\n      \"widgets_values\": [\n        \"disable\",\n        \"CannyEdgePreprocessor\",\n        \"control_lora_rank128_v11p_sd15_canny_fp16.safetensors\",\n        1,\n        100,\n        200,\n        0,\n        1,\n        512,\n        \"disable\",\n        \"OpenposePreprocessor\",\n        \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n        1,\n        0,\n        0,\n        0,\n        1,\n        512,\n        \"disable\",\n        \"InpaintPreprocessor\",\n        \"control_lora_rank128_v11p_sd15_inpaint_fp16.safetensors\",\n        1,\n        0,\n        0,\n        0,\n        1,\n        512\n      ]\n    },\n    {\n      \"id\": 16,\n      \"type\": \"CheckpointLoaderSimple\",\n      \"pos\": [\n        -1297,\n        369\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 98\n      },\n      \"flags\": {},\n      \"order\": 7,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            192\n          ],\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            202\n          ],\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [],\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Checkpoint | id:checkpoint\",\n      \"properties\": {\n        \"Node name for S&R\": \"CheckpointLoaderSimple\"\n      },\n      \"widgets_values\": [\n        \"dreamshaper_8.safetensors\"\n      ]\n    },\n    {\n      \"id\": 76,\n      \"type\": \"LoadLorasFromPrompt\",\n      \"pos\": [\n        -283,\n        168\n      ],\n      \"size\": {\n        \"0\": 462,\n        \"1\": 200\n      },\n      \"flags\": {},\n      \"order\": 18,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 140\n        },\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 203\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            133\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            134\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"STRING\",\n          \"type\": \"STRING\",\n          \"links\": [\n            135\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Loras From Prompt | id:multi_loras_positive_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadLorasFromPrompt\"\n      },\n      \"widgets_values\": [\n        \"\"\n      ]\n    },\n    {\n      \"id\": 109,\n      \"type\": \"CLIPSetLastLayer\",\n      \"pos\": [\n        -845.5936890258794,\n        460.91404269409134\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 13,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 202\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            203,\n            204\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Set Last Layer | id:clip_skip\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPSetLastLayer\"\n      },\n      \"widgets_values\": [\n        -1\n      ]\n    },\n    {\n      \"id\": 87,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -2310,\n        -2190\n      ],\n      \"size\": {\n        \"0\": 306.4342346191406,\n        \"1\": 314\n      },\n      \"flags\": {\n        \"collapsed\": false\n      },\n      \"order\": 8,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            201\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_image_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"ComfyUI_temp_cqoqp_00001_.png\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 94,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -1920,\n        -1670\n      ],\n      \"size\": {\n        \"0\": 285.6000061035156,\n        \"1\": 314\n      },\n      \"flags\": {\n        \"collapsed\": false\n      },\n      \"order\": 9,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            166\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_image_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 96,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -2060,\n        -1240\n      ],\n      \"size\": {\n        \"0\": 285.6000061035156,\n        \"1\": 314\n      },\n      \"flags\": {},\n      \"order\": 10,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            168\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_image_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    }\n  ],\n  \"links\": [\n    [\n      9,\n      8,\n      0,\n      9,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      15,\n      11,\n      0,\n      13,\n      0,\n      \"LATENT\"\n    ],\n    [\n      17,\n      13,\n      0,\n      12,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      36,\n      3,\n      0,\n      8,\n      0,\n      \"LATENT\"\n    ],\n    [\n      78,\n      3,\n      0,\n      55,\n      0,\n      \"LATENT\"\n    ],\n    [\n      79,\n      55,\n      0,\n      11,\n      3,\n      \"LATENT\"\n    ],\n    [\n      82,\n      56,\n      0,\n      8,\n      1,\n      \"VAE\"\n    ],\n    [\n      83,\n      56,\n      0,\n      13,\n      1,\n      \"VAE\"\n    ],\n    [\n      85,\n      56,\n      0,\n      59,\n      1,\n      \"VAE\"\n    ],\n    [\n      86,\n      58,\n      0,\n      60,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      87,\n      60,\n      0,\n      59,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      92,\n      63,\n      0,\n      3,\n      3,\n      \"LATENT\"\n    ],\n    [\n      94,\n      65,\n      0,\n      3,\n      0,\n      \"MODEL\"\n    ],\n    [\n      95,\n      65,\n      0,\n      11,\n      0,\n      \"MODEL\"\n    ],\n    [\n      100,\n      66,\n      0,\n      6,\n      0,\n      \"CLIP\"\n    ],\n    [\n      133,\n      76,\n      0,\n      65,\n      0,\n      \"*\"\n    ],\n    [\n      134,\n      76,\n      1,\n      66,\n      0,\n      \"*\"\n    ],\n    [\n      135,\n      76,\n      2,\n      6,\n      1,\n      \"STRING\"\n    ],\n    [\n      137,\n      78,\n      2,\n      7,\n      1,\n      \"STRING\"\n    ],\n    [\n      138,\n      78,\n      1,\n      7,\n      0,\n      \"CLIP\"\n    ],\n    [\n      140,\n      78,\n      0,\n      76,\n      0,\n      \"MODEL\"\n    ],\n    [\n      142,\n      57,\n      0,\n      56,\n      0,\n      \"*\"\n    ],\n    [\n      153,\n      85,\n      0,\n      11,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      154,\n      85,\n      0,\n      3,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      155,\n      86,\n      0,\n      11,\n      2,\n      \"CONDITIONING\"\n    ],\n    [\n      156,\n      86,\n      0,\n      3,\n      2,\n      \"CONDITIONING\"\n    ],\n    [\n      161,\n      91,\n      0,\n      88,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      162,\n      91,\n      1,\n      89,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      163,\n      91,\n      2,\n      90,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      165,\n      92,\n      0,\n      91,\n      3,\n      \"IMAGE\"\n    ],\n    [\n      166,\n      94,\n      0,\n      91,\n      4,\n      \"IMAGE\"\n    ],\n    [\n      167,\n      93,\n      0,\n      91,\n      5,\n      \"IMAGE\"\n    ],\n    [\n      168,\n      96,\n      0,\n      91,\n      6,\n      \"IMAGE\"\n    ],\n    [\n      169,\n      95,\n      0,\n      91,\n      7,\n      \"IMAGE\"\n    ],\n    [\n      171,\n      7,\n      0,\n      91,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      174,\n      91,\n      4,\n      86,\n      0,\n      \"*\"\n    ],\n    [\n      190,\n      60,\n      0,\n      104,\n      1,\n      \"IMAGE\"\n    ],\n    [\n      191,\n      105,\n      0,\n      104,\n      2,\n      \"CLIP_VISION\"\n    ],\n    [\n      192,\n      16,\n      0,\n      104,\n      0,\n      \"MODEL\"\n    ],\n    [\n      193,\n      104,\n      0,\n      78,\n      0,\n      \"MODEL\"\n    ],\n    [\n      194,\n      104,\n      1,\n      106,\n      1,\n      \"CLIP_VISION_OUTPUT\"\n    ],\n    [\n      195,\n      106,\n      0,\n      91,\n      0,\n      \"CONDITIONING\"\n    ],\n    [\n      196,\n      6,\n      0,\n      106,\n      0,\n      \"CONDITIONING\"\n    ],\n    [\n      197,\n      104,\n      1,\n      107,\n      1,\n      \"CLIP_VISION_OUTPUT\"\n    ],\n    [\n      198,\n      91,\n      3,\n      107,\n      0,\n      \"CONDITIONING\"\n    ],\n    [\n      199,\n      107,\n      0,\n      85,\n      0,\n      \"*\"\n    ],\n    [\n      200,\n      59,\n      0,\n      63,\n      0,\n      \"LATENT\"\n    ],\n    [\n      201,\n      87,\n      0,\n      91,\n      2,\n      \"IMAGE\"\n    ],\n    [\n      202,\n      16,\n      1,\n      109,\n      0,\n      \"CLIP\"\n    ],\n    [\n      203,\n      109,\n      0,\n      76,\n      1,\n      \"CLIP\"\n    ],\n    [\n      204,\n      109,\n      0,\n      78,\n      1,\n      \"CLIP\"\n    ]\n  ],\n  \"groups\": [\n    {\n      \"title\": \"Txt2Img\",\n      \"bounding\": [\n        442,\n        -7,\n        1211,\n        708\n      ],\n      \"color\": \"#a1309b\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Save Intermediate Image\",\n      \"bounding\": [\n        1225,\n        500,\n        516,\n        196\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Hires Fix\",\n      \"bounding\": [\n        1227,\n        17,\n        710,\n        464\n      ],\n      \"color\": \"#b58b2a\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Save Final Image\",\n      \"bounding\": [\n        1949,\n        31,\n        483,\n        199\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Img2img workflow\",\n      \"bounding\": [\n        230,\n        -1475,\n        612,\n        217\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    }\n  ],\n  \"config\": {},\n  \"extra\": {},\n  \"version\": 0.4\n}"
  },
  {
    "path": "typescripts/comfyui/inpaint_api.json",
    "content": "{\n  \"3\": {\n    \"inputs\": {\n      \"seed\": [\n        \"141\",\n        0\n      ],\n      \"steps\": 20,\n      \"cfg\": 7,\n      \"sampler_name\": \"euler_ancestral\",\n      \"scheduler\": \"karras\",\n      \"denoise\": 0.71,\n      \"model\": [\n        \"76\",\n        0\n      ],\n      \"positive\": [\n        \"159\",\n        3\n      ],\n      \"negative\": [\n        \"159\",\n        4\n      ],\n      \"latent_image\": [\n        \"160\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"text\": [\n        \"76\",\n        2\n      ],\n      \"clip\": [\n        \"76\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"text\": [\n        \"78\",\n        2\n      ],\n      \"clip\": [\n        \"78\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"8\": {\n    \"inputs\": {\n      \"samples\": [\n        \"3\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"9\": {\n    \"inputs\": {\n      \"filename_prefix\": \"ComfyUI\",\n      \"images\": [\n        \"8\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"11\": {\n    \"inputs\": {\n      \"seed\": 4820153955672,\n      \"steps\": 20,\n      \"cfg\": 8,\n      \"sampler_name\": \"dpmpp_2m\",\n      \"scheduler\": \"simple\",\n      \"denoise\": 0.4,\n      \"model\": [\n        \"76\",\n        0\n      ],\n      \"positive\": [\n        \"159\",\n        3\n      ],\n      \"negative\": [\n        \"159\",\n        4\n      ],\n      \"latent_image\": [\n        \"55\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"12\": {\n    \"inputs\": {\n      \"filename_prefix\": \"ComfyUI\",\n      \"images\": [\n        \"13\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"13\": {\n    \"inputs\": {\n      \"samples\": [\n        \"11\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"16\": {\n    \"inputs\": {\n      \"ckpt_name\": \"aniverse_v15Pruned.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"55\": {\n    \"inputs\": {\n      \"upscale_method\": \"nearest-exact\",\n      \"scale_by\": 2,\n      \"samples\": [\n        \"3\",\n        0\n      ]\n    },\n    \"class_type\": \"LatentUpscaleBy\"\n  },\n  \"57\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"58\": {\n    \"inputs\": {\n      \"image\": \"04b380cb676f37e52d5963a0982edd5e.jpg\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"76\": {\n    \"inputs\": {\n      \"prompt\": \"young teen:1.2, (cute girl:1.2)\",\n      \"model\": [\n        \"78\",\n        0\n      ],\n      \"clip\": [\n        \"162\",\n        0\n      ]\n    },\n    \"class_type\": \"LoadLorasFromPrompt\"\n  },\n  \"78\": {\n    \"inputs\": {\n      \"prompt\": \"bad hands, text, watermark\",\n      \"model\": [\n        \"16\",\n        0\n      ],\n      \"clip\": [\n        \"162\",\n        0\n      ]\n    },\n    \"class_type\": \"LoadLorasFromPrompt\"\n  },\n  \"83\": {\n    \"inputs\": {\n      \"image\": \"pasted/image (4).png\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"135\": {\n    \"inputs\": {\n      \"content_mask\": \"original\",\n      \"width\": 512,\n      \"height\": 768,\n      \"seed\": [\n        \"141\",\n        0\n      ],\n      \"init_image\": [\n        \"58\",\n        0\n      ],\n      \"mask\": [\n        \"83\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"ContentMaskLatent\"\n  },\n  \"141\": {\n    \"inputs\": {\n      \"seed\": 519416762507340\n    },\n    \"class_type\": \"APS_Seed\"\n  },\n  \"155\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 768,\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"156\": {\n    \"inputs\": {\n      \"images\": [\n        \"159\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"157\": {\n    \"inputs\": {\n      \"images\": [\n        \"159\",\n        1\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"158\": {\n    \"inputs\": {\n      \"images\": [\n        \"159\",\n        2\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"159\": {\n    \"inputs\": {\n      \"is_enabled_1\": \"disable\",\n      \"preprocessor_name_1\": \"OpenposePreprocessor\",\n      \"control_net_name_1\": \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n      \"strength_1\": 1,\n      \"threshold_a_1\": 100,\n      \"threshold_b_1\": 200,\n      \"start_percent_1\": 0,\n      \"end_percent_1\": 1,\n      \"resolution_1\": 512,\n      \"is_enabled_2\": \"disable\",\n      \"preprocessor_name_2\": \"OpenposePreprocessor\",\n      \"control_net_name_2\": \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n      \"strength_2\": 1,\n      \"threshold_a_2\": 0,\n      \"threshold_b_2\": 0,\n      \"start_percent_2\": 0,\n      \"end_percent_2\": 1,\n      \"resolution_2\": 512,\n      \"is_enabled_3\": \"enable\",\n      \"preprocessor_name_3\": \"InpaintPreprocessor\",\n      \"control_net_name_3\": \"control_lora_rank128_v11p_sd15_inpaint_fp16.safetensors\",\n      \"strength_3\": 1,\n      \"threshold_a_3\": 0,\n      \"threshold_b_3\": 0,\n      \"start_percent_3\": 0,\n      \"end_percent_3\": 1,\n      \"resolution_3\": 512,\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"7\",\n        0\n      ],\n      \"image_1\": [\n        \"58\",\n        0\n      ],\n      \"mask_1\": [\n        \"83\",\n        0\n      ],\n      \"image_2\": [\n        \"58\",\n        0\n      ],\n      \"mask_2\": [\n        \"83\",\n        0\n      ],\n      \"image_3\": [\n        \"58\",\n        0\n      ],\n      \"mask_3\": [\n        \"83\",\n        0\n      ]\n    },\n    \"class_type\": \"ControlNetScript\"\n  },\n  \"160\": {\n    \"inputs\": {\n      \"amount\": 1,\n      \"samples\": [\n        \"135\",\n        0\n      ]\n    },\n    \"class_type\": \"RepeatLatentBatch\"\n  },\n  \"162\": {\n    \"inputs\": {\n      \"stop_at_clip_layer\": -1,\n      \"clip\": [\n        \"16\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPSetLastLayer\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/inpaint_workflow.json",
    "content": "{\n  \"last_node_id\": 162,\n  \"last_link_id\": 313,\n  \"nodes\": [\n    {\n      \"id\": 13,\n      \"type\": \"VAEDecode\",\n      \"pos\": [\n        2680,\n        940\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 35,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 15\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 201\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            17\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEDecode\"\n      }\n    },\n    {\n      \"id\": 66,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        160,\n        1010\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 23,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 134\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            100\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 114,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        960,\n        1580\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 10,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 195\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            196\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 116,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        2510,\n        780\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 14,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 202,\n          \"slot_index\": 0\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            201\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 113,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        69,\n        1605\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 6,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 193\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            195,\n            197\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 8,\n      \"type\": \"VAEDecode\",\n      \"pos\": [\n        1312,\n        1545\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 32,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 278\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 196\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            9\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEDecode\"\n      }\n    },\n    {\n      \"id\": 115,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        369,\n        420\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 11,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 197\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            202,\n            247\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 55,\n      \"type\": \"LatentUpscaleBy\",\n      \"pos\": [\n        1876,\n        1198\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 82\n      },\n      \"flags\": {},\n      \"order\": 31,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 78\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            79\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Upscale Latent By | id:scaler\",\n      \"properties\": {\n        \"Node name for S&R\": \"LatentUpscaleBy\"\n      },\n      \"widgets_values\": [\n        \"nearest-exact\",\n        2\n      ]\n    },\n    {\n      \"id\": 65,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        190,\n        920\n      ],\n      \"size\": [\n        82,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 22,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 133\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            95,\n            263\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 78,\n      \"type\": \"LoadLorasFromPrompt\",\n      \"pos\": [\n        -2610,\n        1250\n      ],\n      \"size\": {\n        \"0\": 462,\n        \"1\": 200\n      },\n      \"flags\": {},\n      \"order\": 12,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 141\n        },\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 309\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            140\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            138\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"STRING\",\n          \"type\": \"STRING\",\n          \"links\": [\n            137\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Loras From Prompt | id:multi_loras_negative_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadLorasFromPrompt\"\n      },\n      \"widgets_values\": [\n        \"bad hands, text, watermark\"\n      ]\n    },\n    {\n      \"id\": 57,\n      \"type\": \"VAELoader\",\n      \"pos\": [\n        -396,\n        1595\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 0,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            193\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Load VAE | id:vae\",\n      \"properties\": {\n        \"Node name for S&R\": \"VAELoader\"\n      },\n      \"widgets_values\": [\n        \"vae-ft-mse-840000-ema-pruned.safetensors\"\n      ]\n    },\n    {\n      \"id\": 142,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        2490,\n        150\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 20,\n      \"mode\": 2,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 261\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 149,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        2250,\n        450\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 21,\n      \"mode\": 2,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 277\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 148,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        2270,\n        -116\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 19,\n      \"mode\": 2,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 276\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 155,\n      \"type\": \"EmptyLatentImage\",\n      \"pos\": [\n        1329.5197187499998,\n        447.17789685058585\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 106\n      },\n      \"flags\": {},\n      \"order\": 1,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"EmptyLatentImage\"\n      },\n      \"widgets_values\": [\n        512,\n        768,\n        1\n      ]\n    },\n    {\n      \"id\": 7,\n      \"type\": \"CLIPTextEncode\",\n      \"pos\": [\n        -1760,\n        1050\n      ],\n      \"size\": {\n        \"0\": 425.27801513671875,\n        \"1\": 180.6060791015625\n      },\n      \"flags\": {},\n      \"order\": 17,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 138\n        },\n        {\n          \"name\": \"text\",\n          \"type\": \"STRING\",\n          \"link\": 137,\n          \"widget\": {\n            \"name\": \"text\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            295\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Text Encode (Prompt) | id:negative_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPTextEncode\"\n      },\n      \"widgets_values\": [\n        \"bad hands, text, watermark\\n\"\n      ]\n    },\n    {\n      \"id\": 9,\n      \"type\": \"SaveImage\",\n      \"pos\": [\n        1546,\n        1609\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 282.4336242675781\n      },\n      \"flags\": {},\n      \"order\": 34,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 9\n        }\n      ],\n      \"title\": \"Save Image | id:first_pass_output\",\n      \"properties\": {},\n      \"widgets_values\": [\n        \"ComfyUI\"\n      ]\n    },\n    {\n      \"id\": 153,\n      \"type\": \"ImageToMask\",\n      \"pos\": [\n        -720,\n        -840\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 13,\n      \"mode\": 4,\n      \"inputs\": [\n        {\n          \"name\": \"image\",\n          \"type\": \"IMAGE\",\n          \"link\": 283\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": [],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"ImageToMask\"\n      },\n      \"widgets_values\": [\n        \"red\"\n      ]\n    },\n    {\n      \"id\": 58,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        933,\n        -569\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 314\n      },\n      \"flags\": {},\n      \"order\": 2,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            258,\n            274\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:init_image\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"04b380cb676f37e52d5963a0982edd5e.jpg\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 3,\n      \"type\": \"KSampler\",\n      \"pos\": [\n        757,\n        831\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 446\n      },\n      \"flags\": {},\n      \"order\": 30,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 263\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 298,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 299\n        },\n        {\n          \"name\": \"latent_image\",\n          \"type\": \"LATENT\",\n          \"link\": 306\n        },\n        {\n          \"name\": \"seed\",\n          \"type\": \"INT\",\n          \"link\": 260,\n          \"widget\": {\n            \"name\": \"seed\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            78,\n            278\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"KSampler | id:sampler\",\n      \"properties\": {\n        \"Node name for S&R\": \"KSampler\"\n      },\n      \"widgets_values\": [\n        63028417688397,\n        \"randomize\",\n        20,\n        7,\n        \"euler_ancestral\",\n        \"karras\",\n        0.71\n      ]\n    },\n    {\n      \"id\": 12,\n      \"type\": \"SaveImage\",\n      \"pos\": [\n        3162,\n        1131\n      ],\n      \"size\": {\n        \"0\": 407.53717041015625,\n        \"1\": 468.13226318359375\n      },\n      \"flags\": {},\n      \"order\": 36,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 17\n        }\n      ],\n      \"title\": \"Save Image | id:hires_output\",\n      \"properties\": {},\n      \"widgets_values\": [\n        \"ComfyUI\"\n      ]\n    },\n    {\n      \"id\": 121,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        2069,\n        410\n      ],\n      \"size\": [\n        90.4,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 18,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 290\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            305\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      },\n      \"color\": \"#223\",\n      \"bgcolor\": \"#335\"\n    },\n    {\n      \"id\": 160,\n      \"type\": \"RepeatLatentBatch\",\n      \"pos\": [\n        1752,\n        517\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 24,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 305\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            306\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Repeat Latent Batch | id:latent_batch\",\n      \"properties\": {\n        \"Node name for S&R\": \"RepeatLatentBatch\"\n      },\n      \"widgets_values\": [\n        1\n      ]\n    },\n    {\n      \"id\": 157,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        -610,\n        -240\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 28,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 292\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 156,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        -860,\n        -240\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 27,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 291\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 158,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        -330,\n        -212\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 29,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 293\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 147,\n      \"type\": \"ImageScale\",\n      \"pos\": [\n        -1084,\n        -646\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 130\n      },\n      \"flags\": {},\n      \"order\": 7,\n      \"mode\": 4,\n      \"inputs\": [\n        {\n          \"name\": \"image\",\n          \"type\": \"IMAGE\",\n          \"link\": 274\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            296,\n            303,\n            307\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"ImageScale\"\n      },\n      \"widgets_values\": [\n        \"nearest-exact\",\n        512,\n        768,\n        \"disabled\"\n      ]\n    },\n    {\n      \"id\": 152,\n      \"type\": \"ImageScale\",\n      \"pos\": [\n        -1030,\n        -1050\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 130\n      },\n      \"flags\": {},\n      \"order\": 9,\n      \"mode\": 4,\n      \"inputs\": [\n        {\n          \"name\": \"image\",\n          \"type\": \"IMAGE\",\n          \"link\": 282\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            283,\n            302,\n            304,\n            308\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"ImageScale\"\n      },\n      \"widgets_values\": [\n        \"nearest-exact\",\n        512,\n        768,\n        \"disabled\"\n      ]\n    },\n    {\n      \"id\": 16,\n      \"type\": \"CheckpointLoaderSimple\",\n      \"pos\": [\n        -3298,\n        1138\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 98\n      },\n      \"flags\": {},\n      \"order\": 3,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            141\n          ],\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            311\n          ],\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [],\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Checkpoint | id:checkpoint\",\n      \"properties\": {\n        \"Node name for S&R\": \"CheckpointLoaderSimple\"\n      },\n      \"widgets_values\": [\n        \"aniverse_v15Pruned.safetensors\"\n      ]\n    },\n    {\n      \"id\": 162,\n      \"type\": \"CLIPSetLastLayer\",\n      \"pos\": [\n        -2959,\n        1098\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 8,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 311\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            309,\n            310\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Set Last Layer | id:clip_skip\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPSetLastLayer\"\n      },\n      \"widgets_values\": [\n        -1\n      ]\n    },\n    {\n      \"id\": 6,\n      \"type\": \"CLIPTextEncode\",\n      \"pos\": [\n        -1740,\n        820\n      ],\n      \"size\": {\n        \"0\": 422.84503173828125,\n        \"1\": 164.31304931640625\n      },\n      \"flags\": {},\n      \"order\": 25,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 100\n        },\n        {\n          \"name\": \"text\",\n          \"type\": \"STRING\",\n          \"link\": 135,\n          \"widget\": {\n            \"name\": \"text\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            294\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Text Encode (Prompt) | id:positive_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPTextEncode\"\n      },\n      \"widgets_values\": [\n        \"lora_bright_style girl\"\n      ]\n    },\n    {\n      \"id\": 159,\n      \"type\": \"ControlNetScript\",\n      \"pos\": [\n        -1160,\n        70\n      ],\n      \"size\": {\n        \"0\": 506.0240173339844,\n        \"1\": 822\n      },\n      \"flags\": {},\n      \"order\": 26,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 294\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 295,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"image_1\",\n          \"type\": \"IMAGE\",\n          \"link\": 296\n        },\n        {\n          \"name\": \"mask_1\",\n          \"type\": \"IMAGE\",\n          \"link\": 304,\n          \"slot_index\": 3\n        },\n        {\n          \"name\": \"image_2\",\n          \"type\": \"IMAGE\",\n          \"link\": 303\n        },\n        {\n          \"name\": \"mask_2\",\n          \"type\": \"IMAGE\",\n          \"link\": 302\n        },\n        {\n          \"name\": \"image_3\",\n          \"type\": \"IMAGE\",\n          \"link\": 307\n        },\n        {\n          \"name\": \"mask_3\",\n          \"type\": \"IMAGE\",\n          \"link\": 308\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"preprocessed_image_1\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            291\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"preprocessed_image_2\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            292\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"preprocessed_image_3\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            293\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            298,\n            312\n          ],\n          \"shape\": 3,\n          \"slot_index\": 3\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            299,\n            313\n          ],\n          \"shape\": 3,\n          \"slot_index\": 4\n        }\n      ],\n      \"title\": \"ControlNet Script | id:controlnet_script\",\n      \"properties\": {\n        \"Node name for S&R\": \"ControlNetScript\"\n      },\n      \"widgets_values\": [\n        \"disable\",\n        \"OpenposePreprocessor\",\n        \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n        1,\n        100,\n        200,\n        0,\n        1,\n        512,\n        \"disable\",\n        \"OpenposePreprocessor\",\n        \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n        1,\n        0,\n        0,\n        0,\n        1,\n        512,\n        \"enable\",\n        \"InpaintPreprocessor\",\n        \"control_lora_rank128_v11p_sd15_inpaint_fp16.safetensors\",\n        1,\n        0,\n        0,\n        0,\n        1,\n        512\n      ]\n    },\n    {\n      \"id\": 141,\n      \"type\": \"APS_Seed\",\n      \"pos\": [\n        711,\n        429\n      ],\n      \"size\": {\n        \"0\": 361.20001220703125,\n        \"1\": 82\n      },\n      \"flags\": {},\n      \"order\": 4,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"s\",\n          \"type\": \"INT\",\n          \"links\": [\n            259,\n            260\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Auto-Photoshop-SD Seed | id:first_pass_seed\",\n      \"properties\": {\n        \"Node name for S&R\": \"APS_Seed\"\n      },\n      \"widgets_values\": [\n        519416762507340,\n        \"fixed\"\n      ]\n    },\n    {\n      \"id\": 11,\n      \"type\": \"KSampler\",\n      \"pos\": [\n        2227,\n        1000\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 474\n      },\n      \"flags\": {},\n      \"order\": 33,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 95,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 312,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 313,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"latent_image\",\n          \"type\": \"LATENT\",\n          \"link\": 79,\n          \"slot_index\": 3\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            15\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"KSampler | id:hires_sampler\",\n      \"properties\": {\n        \"Node name for S&R\": \"KSampler\"\n      },\n      \"widgets_values\": [\n        4820153955672,\n        \"fixed\",\n        20,\n        8,\n        \"dpmpp_2m\",\n        \"simple\",\n        0.4\n      ]\n    },\n    {\n      \"id\": 76,\n      \"type\": \"LoadLorasFromPrompt\",\n      \"pos\": [\n        -2600,\n        980\n      ],\n      \"size\": {\n        \"0\": 462,\n        \"1\": 200\n      },\n      \"flags\": {},\n      \"order\": 16,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 140\n        },\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 310\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            133\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            134\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"STRING\",\n          \"type\": \"STRING\",\n          \"links\": [\n            135\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Loras From Prompt | id:multi_loras_positive_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadLorasFromPrompt\"\n      },\n      \"widgets_values\": [\n        \"young teen:1.2, (cute girl:1.2)\"\n      ]\n    },\n    {\n      \"id\": 83,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        422,\n        -246\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 314\n      },\n      \"flags\": {},\n      \"order\": 5,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            257,\n            282\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": [],\n          \"shape\": 3,\n          \"slot_index\": 1\n        }\n      ],\n      \"title\": \"Load Image | id:mask_image\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"pasted/image (4).png\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 135,\n      \"type\": \"ContentMaskLatent\",\n      \"pos\": [\n        1312,\n        89\n      ],\n      \"size\": [\n        418.1999816894531,\n        214\n      ],\n      \"flags\": {},\n      \"order\": 15,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"init_image\",\n          \"type\": \"IMAGE\",\n          \"link\": 258\n        },\n        {\n          \"name\": \"mask\",\n          \"type\": \"IMAGE\",\n          \"link\": 257\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 247,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"seed\",\n          \"type\": \"INT\",\n          \"link\": 259,\n          \"widget\": {\n            \"name\": \"seed\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"latents\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            290\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"original_preview\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            276\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"latent_noise_preview\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            261\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"latent_nothing_preview\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            277\n          ],\n          \"shape\": 3,\n          \"slot_index\": 3\n        }\n      ],\n      \"title\": \"Content Mask Latent | id:content_mask_latent\",\n      \"properties\": {\n        \"Node name for S&R\": \"ContentMaskLatent\"\n      },\n      \"widgets_values\": [\n        \"original\",\n        512,\n        768,\n        185734188050359,\n        \"randomize\"\n      ]\n    }\n  ],\n  \"links\": [\n    [\n      9,\n      8,\n      0,\n      9,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      15,\n      11,\n      0,\n      13,\n      0,\n      \"LATENT\"\n    ],\n    [\n      17,\n      13,\n      0,\n      12,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      78,\n      3,\n      0,\n      55,\n      0,\n      \"LATENT\"\n    ],\n    [\n      79,\n      55,\n      0,\n      11,\n      3,\n      \"LATENT\"\n    ],\n    [\n      95,\n      65,\n      0,\n      11,\n      0,\n      \"MODEL\"\n    ],\n    [\n      100,\n      66,\n      0,\n      6,\n      0,\n      \"CLIP\"\n    ],\n    [\n      133,\n      76,\n      0,\n      65,\n      0,\n      \"*\"\n    ],\n    [\n      134,\n      76,\n      1,\n      66,\n      0,\n      \"*\"\n    ],\n    [\n      135,\n      76,\n      2,\n      6,\n      1,\n      \"STRING\"\n    ],\n    [\n      137,\n      78,\n      2,\n      7,\n      1,\n      \"STRING\"\n    ],\n    [\n      138,\n      78,\n      1,\n      7,\n      0,\n      \"CLIP\"\n    ],\n    [\n      140,\n      78,\n      0,\n      76,\n      0,\n      \"MODEL\"\n    ],\n    [\n      141,\n      16,\n      0,\n      78,\n      0,\n      \"MODEL\"\n    ],\n    [\n      193,\n      57,\n      0,\n      113,\n      0,\n      \"*\"\n    ],\n    [\n      195,\n      113,\n      0,\n      114,\n      0,\n      \"*\"\n    ],\n    [\n      196,\n      114,\n      0,\n      8,\n      1,\n      \"VAE\"\n    ],\n    [\n      197,\n      113,\n      0,\n      115,\n      0,\n      \"*\"\n    ],\n    [\n      201,\n      116,\n      0,\n      13,\n      1,\n      \"VAE\"\n    ],\n    [\n      202,\n      115,\n      0,\n      116,\n      0,\n      \"*\"\n    ],\n    [\n      247,\n      115,\n      0,\n      135,\n      2,\n      \"VAE\"\n    ],\n    [\n      257,\n      83,\n      0,\n      135,\n      1,\n      \"IMAGE\"\n    ],\n    [\n      258,\n      58,\n      0,\n      135,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      259,\n      141,\n      0,\n      135,\n      3,\n      \"INT\"\n    ],\n    [\n      260,\n      141,\n      0,\n      3,\n      4,\n      \"INT\"\n    ],\n    [\n      261,\n      135,\n      2,\n      142,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      263,\n      65,\n      0,\n      3,\n      0,\n      \"MODEL\"\n    ],\n    [\n      274,\n      58,\n      0,\n      147,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      276,\n      135,\n      1,\n      148,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      277,\n      135,\n      3,\n      149,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      278,\n      3,\n      0,\n      8,\n      0,\n      \"LATENT\"\n    ],\n    [\n      282,\n      83,\n      0,\n      152,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      283,\n      152,\n      0,\n      153,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      290,\n      135,\n      0,\n      121,\n      0,\n      \"*\"\n    ],\n    [\n      291,\n      159,\n      0,\n      156,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      292,\n      159,\n      1,\n      157,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      293,\n      159,\n      2,\n      158,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      294,\n      6,\n      0,\n      159,\n      0,\n      \"CONDITIONING\"\n    ],\n    [\n      295,\n      7,\n      0,\n      159,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      296,\n      147,\n      0,\n      159,\n      2,\n      \"IMAGE\"\n    ],\n    [\n      298,\n      159,\n      3,\n      3,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      299,\n      159,\n      4,\n      3,\n      2,\n      \"CONDITIONING\"\n    ],\n    [\n      302,\n      152,\n      0,\n      159,\n      5,\n      \"IMAGE\"\n    ],\n    [\n      303,\n      147,\n      0,\n      159,\n      4,\n      \"IMAGE\"\n    ],\n    [\n      304,\n      152,\n      0,\n      159,\n      3,\n      \"IMAGE\"\n    ],\n    [\n      305,\n      121,\n      0,\n      160,\n      0,\n      \"LATENT\"\n    ],\n    [\n      306,\n      160,\n      0,\n      3,\n      3,\n      \"LATENT\"\n    ],\n    [\n      307,\n      147,\n      0,\n      159,\n      6,\n      \"IMAGE\"\n    ],\n    [\n      308,\n      152,\n      0,\n      159,\n      7,\n      \"IMAGE\"\n    ],\n    [\n      309,\n      162,\n      0,\n      78,\n      1,\n      \"CLIP\"\n    ],\n    [\n      310,\n      162,\n      0,\n      76,\n      1,\n      \"CLIP\"\n    ],\n    [\n      311,\n      16,\n      1,\n      162,\n      0,\n      \"CLIP\"\n    ],\n    [\n      312,\n      159,\n      3,\n      11,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      313,\n      159,\n      4,\n      11,\n      2,\n      \"CONDITIONING\"\n    ]\n  ],\n  \"groups\": [\n    {\n      \"title\": \"Txt2Img\",\n      \"bounding\": [\n        433,\n        692,\n        1386,\n        1295\n      ],\n      \"color\": \"#a1309b\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Save Intermediate Image\",\n      \"bounding\": [\n        1283,\n        1497,\n        529,\n        440\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Hires Fix\",\n      \"bounding\": [\n        1864,\n        887,\n        762,\n        544\n      ],\n      \"color\": \"#b58b2a\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Save Final Image\",\n      \"bounding\": [\n        2671,\n        785,\n        976,\n        856\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"inpaint workflow\",\n      \"bounding\": [\n        -248,\n        -966,\n        697,\n        249\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    }\n  ],\n  \"config\": {},\n  \"extra\": {},\n  \"version\": 0.4\n}"
  },
  {
    "path": "typescripts/comfyui/main_ui.tsx",
    "content": "import txt2img from './txt2img_workflow.json'\nimport txt2img_api from './txt2img_api.json'\n\nimport img2img from './img2img_workflow.json'\nimport img2img_api from './img2img_api.json'\n\nimport inpaint from './inpaint_workflow.json'\nimport inpaint_api from './inpaint_api.json'\n\nimport vae_settings from '../settings/vae'\nimport sd_tab_util from '../sd_tab/util'\nimport comfyui_util from './util'\nimport util from './util'\nimport { store } from './util'\n\nimport { base64UrlToBase64, copyJson } from '../util/ts/general'\nimport { session_store } from '../stores'\nimport ControlNetStore from '../controlnet/store'\nimport { setControlDetectMapSrc } from '../controlnet/entry'\n\n// Function to parse metadata from a title string\nfunction parseMetadata(title: string) {\n    if (!title) return {}\n    // Split the title into parts using the \"|\" character and trim whitespace from each part\n\n    var parts = title.split('|').map((part) => part.trim())\n    // Take the last part as the metadata\n    var metadataPart = parts[parts.length - 1]\n    // Initialize an empty object to store the key-value pairs\n    var result: Record<string, string> = {}\n    // If there is more than one part, there is metadata to parse\n    if (parts.length > 1) {\n        // Split the metadata into pairs using the \",\" character and trim whitespace from each pair\n        var pairs = metadataPart.split(',').map((pair) => pair.trim())\n\n        // For each pair...\n        for (var i = 0; i < pairs.length; i++) {\n            // If the pair includes a \":\" character, it is a key-value pair\n            if (pairs[i].includes(':')) {\n                // Split the pair into a key and a value using the \":\" character and trim whitespace\n                var pair = pairs[i].split(':').map((part) => part.trim())\n\n                // Add the key-value pair to the result object\n                result[pair[0]] = pair[1]\n            }\n        }\n    }\n\n    // Return the result object containing the key-value pairs\n    return result\n}\n\nfunction getInput(node: any, name: string) {\n    const input = node.inputs.filter((input: any) => {\n        return input?.widget?.name === name\n    })?.[0]\n    return input\n}\nfunction getNode(nodes: any[], node_id: string) {\n    const node = nodes.filter((node: any) => {\n        return parseInt(node.id) === parseInt(node_id)\n    })?.[0]\n    return node\n}\nfunction getNodeByNameId(nodes: any[], node_name_id: string) {\n    const node = nodes.filter((node: any) => {\n        const node_metadata = parseMetadata(node.title)\n        return node_metadata.id === node_name_id\n    })?.[0]\n    return node\n}\n\nfunction getPromptNodeByNameId(\n    nodes: any[], //nodes from workflow.json\n    prompt: any, //prompt from api.json\n    node_name_id: string // name_id I'm using to get access to nodes by their name\n) {\n    const node = getNodeByNameId(nodes, node_name_id)\n    const prompt_node = node?.id ? prompt[node.id] : {}\n\n    return prompt_node\n}\nfunction setInputValue(\n    nodes: any[],\n    prompt: any,\n    node_name_id: string,\n    input_name: string,\n    new_value: any\n) {\n    try {\n        var prompt_node = getPromptNodeByNameId(nodes, prompt, node_name_id)\n        prompt_node.inputs[input_name] = new_value\n    } catch (e) {\n        console.error(\n            `Node Name ID:\\n${node_name_id}\\n` +\n                `Input Name:\\n${input_name}\\n` +\n                `New Value:\\n${new_value}\\n` +\n                `Prompt Node:\\n${prompt_node}\\n` +\n                `Error:\\n${e}`\n        )\n    }\n}\nfunction getLink(links: any[], link_id: number) {\n    return links.filter((link: any) => {\n        return link[0] === link_id\n    })?.[0]\n}\n\nfunction getNodesFromLink(link: any) {\n    return {\n        from_node: { id: link[1], input_index: link[2] },\n        to_node: { id: link[3], input_index: link[4] },\n    }\n}\nfunction mutePromptNode(nodes: any[], prompt: any, node_name_id: string) {\n    const node = getNodeByNameId(nodes, node_name_id)\n    delete prompt[node.id]\n    return prompt\n}\nconst txt2img_map: Record<string, any> = {\n    model: 'checkpoint.ckpt_name',\n    comfy_clip_skip: 'clip_skip.stop_at_clip_layer',\n    vae: 'vae.vae_name',\n    width: 'latent_image.width',\n    height: 'latent_image.height',\n    batch_size: 'latent_image.batch_size',\n    prompt: 'multi_loras_positive_prompt.prompt',\n    negative_prompt: 'multi_loras_negative_prompt.prompt',\n\n    //sampler node\n\n    seed: 'sampler.seed',\n    steps: 'sampler.steps',\n    cfg_scale: 'sampler.cfg',\n    sampler_index: 'sampler.sampler_name',\n    // scheduler: 'normal',\n    // denoising_strength: 'sampler.denoise', // keep it at default value 1.0\n\n    //hires_node node:\n    hr_scale: 'scaler.scale_by',\n    upscale_method: 'nearest_exact',\n\n    hr_seed: 'hires_sampler.seed',\n    hr_second_pass_steps: 'hires_sampler.steps',\n    // hr_cfg: 'hires_sampler.cfg', // keep at default value 0.5\n    // hr_sampler_name: 'hires_sampler.sampler_name',\n    // hr_scheduler: 'normal',\n    hr_denoising_strength: 'hires_sampler.denoise',\n}\nconst controlnet_txt2img_map: Record<string, any> = {\n    comfy_input_image: 'controlnet_script.image', //map controlnet_units[unit_index].input_image from base64 string to comfy image filename\n    comfy_mask: 'controlnet_script.mask', //map controlnet_units[unit_index].mask from base64 string to comfy image filename\n    comfy_enabled: 'controlnet_script.is_enabled', //map controlnet_units[unit_index].enabled from boolean [true,false] to ['enable', 'disable']\n    module: 'controlnet_script.preprocessor_name',\n    model: 'controlnet_script.control_net_name',\n    weight: 'controlnet_script.strength',\n    guidance_start: 'controlnet_script.start_percent',\n    guidance_end: 'controlnet_script.end_percent',\n    processor_res: 'controlnet_script.resolution',\n    threshold_a: 'controlnet_script.threshold_a',\n    threshold_b: 'controlnet_script.threshold_b',\n}\nconst img2img_map: Record<string, any> = {\n    init_image: 'init_image.image', // note: this is not init_images but init_image\n    model: 'checkpoint.ckpt_name',\n    comfy_clip_skip: 'clip_skip.stop_at_clip_layer',\n    vae: 'vae.vae_name',\n    width: 'init_image_scale.width',\n    height: 'init_image_scale.height',\n    batch_size: 'latent_batch.amount',\n    // prompt: 'positive_prompt.text',\n    prompt: 'multi_loras_positive_prompt.prompt',\n    negative_prompt: 'multi_loras_negative_prompt.prompt',\n\n    //sampler node\n\n    seed: 'sampler.seed',\n    steps: 'sampler.steps',\n    cfg_scale: 'sampler.cfg',\n    sampler_index: 'sampler.sampler_name',\n    // scheduler: 'normal',\n    denoising_strength: 'sampler.denoise',\n\n    //hires_node node:\n    hr_scale: 'scaler.scale_by',\n    upscale_method: 'nearest_exact',\n\n    hr_seed: 'hires_sampler.seed',\n    hr_second_pass_steps: 'hires_sampler.steps',\n    // hr_cfg: 'hires_sampler.cfg', // keep at default value 0.5\n    // hr_sampler_name: 'hires_sampler.sampler_name',\n    // hr_scheduler: 'normal',\n    hr_denoising_strength: 'hires_sampler.denoise',\n}\nconst inpaint_map: Record<string, any> = {\n    init_image: 'init_image.image', // note: this is not init_images but init_image\n    comfy_mask: 'mask_image.image',\n    model: 'checkpoint.ckpt_name',\n    comfy_clip_skip: 'clip_skip.stop_at_clip_layer',\n    vae: 'vae.vae_name',\n    width: 'content_mask_latent.width',\n    height: 'content_mask_latent.height',\n    batch_size: 'latent_batch.amount',\n    // prompt: 'positive_prompt.text',\n    prompt: 'multi_loras_positive_prompt.prompt',\n    negative_prompt: 'multi_loras_negative_prompt.prompt',\n\n    comfy_content_mask: 'content_mask_latent.content_mask',\n\n    //sampler node\n\n    seed: 'first_pass_seed.seed',\n    steps: 'sampler.steps',\n    cfg_scale: 'sampler.cfg',\n    sampler_index: 'sampler.sampler_name',\n    // scheduler: 'normal',\n    denoising_strength: 'sampler.denoise',\n\n    //hires_node node:\n    hr_scale: 'scaler.scale_by',\n    upscale_method: 'nearest_exact',\n\n    hr_seed: 'hires_sampler.seed',\n    hr_second_pass_steps: 'hires_sampler.steps',\n    // hr_cfg: 'hires_sampler.cfg', // keep at default value 0.5\n    // hr_sampler_name: 'hires_sampler.sampler_name',\n    // hr_scheduler: 'normal',\n    hr_denoising_strength: 'hires_sampler.denoise',\n}\n\nexport async function reuseOrUploadComfyImage(\n    base64: string,\n    all_uploaded_images: Record<string, any>,\n    type = 'input'\n) {\n    let image_path: string = ''\n    if (all_uploaded_images[base64]) {\n        image_path = all_uploaded_images[base64]\n    } else {\n        const new_loaded_image = await util.uploadImage(false, base64, type)\n        console.log('new_loaded_image: ', new_loaded_image)\n        if (new_loaded_image) {\n            const { subfolder, name, type } = new_loaded_image\n            image_path = subfolder !== '' ? `${subfolder}/${name}` : `${name}`\n            store.data.uploaded_images_list = [\n                ...store.data.uploaded_images_list,\n                image_path,\n            ]\n\n            all_uploaded_images[base64] = image_path\n        }\n    }\n    return image_path\n}\nasync function addMissingSettings(plugin_settings: Record<string, any>) {\n    plugin_settings['vae'] = vae_settings.store.data.current_vae\n    plugin_settings['model'] = sd_tab_util.store.data.selected_model\n    plugin_settings['hr_denoising_strength'] =\n        sd_tab_util.store.data.hr_denoising_strength\n    plugin_settings['hr_sampler_name'] = sd_tab_util.store.data.sampler_name // use the same sampler for the first and second pass (hires) upscale sampling steps\n    plugin_settings['comfy_clip_skip'] = -1 * plugin_settings['clip_skip']\n    if ('init_images' in plugin_settings) {\n        const base64 = plugin_settings['init_images'][0]\n\n        plugin_settings['init_image'] = await reuseOrUploadComfyImage(\n            base64,\n            store.data.base64_to_uploaded_images_names,\n            'input'\n        )\n    }\n    if ('mask' in plugin_settings) {\n        const base64 = plugin_settings['mask']\n\n        plugin_settings['comfy_mask'] = await reuseOrUploadComfyImage(\n            base64,\n            store.data.base64_to_uploaded_images_names,\n            'input'\n        )\n    }\n\n    //calculate positive random seed if seed is -1\n    const random_seed: bigint = util.getRandomBigIntApprox(\n        0n,\n        18446744073709552000n\n    )\n\n    plugin_settings['seed'] =\n        parseInt(plugin_settings['seed']) === -1\n            ? random_seed.toString()\n            : plugin_settings['seed'] // use the same as the main seed\n\n    session_store.data.last_seed = plugin_settings['seed']\n    plugin_settings['hr_seed'] = plugin_settings['seed']\n\n    return plugin_settings\n}\n\nasync function addMissingControlnetSettings(\n    plugin_settings: Record<string, any>\n) {\n    plugin_settings['disableControlNetTab'] =\n        ControlNetStore.disableControlNetTab\n    for (const unit of plugin_settings['controlnet_units']) {\n        unit['comfy_enabled'] =\n            !plugin_settings['disableControlNetTab'] && unit.enabled\n                ? 'enable'\n                : 'disable'\n\n        unit['comfy_input_image'] = ''\n        unit['comfy_mask'] = ''\n        if ('input_image' in unit && unit['input_image'] !== '') {\n            const base64 = unit['input_image']\n            unit['comfy_input_image'] = await reuseOrUploadComfyImage(\n                base64,\n                store.data.base64_to_uploaded_images_names,\n                'input'\n            )\n        }\n        if ('mask' in unit && unit['mask'] !== '') {\n            //if mask have been set manually\n            const base64 = unit['mask']\n\n            unit['comfy_mask'] = await reuseOrUploadComfyImage(\n                base64,\n                store.data.base64_to_uploaded_images_names,\n                'input'\n            )\n        } else if ('comfy_mask' in plugin_settings) {\n            // use the mask from the main ui (inpaint and outpaint mode)\n\n            unit['comfy_mask'] = plugin_settings['comfy_mask']\n        }\n\n        //set model and module to 'None' if no item has been selection, so comfyui won't through an error\n        unit['model'] =\n            unit['model'] === '' || unit['comfy_enabled'] === 'disable'\n                ? 'None'\n                : unit['model']\n        unit['module'] =\n            unit['module'] === '' || unit['comfy_enabled'] === 'disable'\n                ? 'None'\n                : unit['module']\n    }\n    return plugin_settings\n}\nasync function mapPluginSettingsToComfyuiPrompt(\n    nodes: any[],\n    prompt: any,\n    plugin_settings: any,\n    mode_map: any\n) {\n    try {\n        // const plugin_param = 'steps'\n        plugin_settings = await addMissingSettings(plugin_settings)\n        function mapPluginInputToComfyInput(\n            plugin_settings: Record<string, any>,\n            plugin_param: string,\n            node_name_id: string,\n            input_name: string\n        ) {\n            if (plugin_param in plugin_settings) {\n                setInputValue(\n                    nodes,\n                    prompt,\n                    node_name_id,\n                    input_name,\n                    plugin_settings[plugin_param]\n                )\n            }\n        }\n\n        Object.keys(mode_map).forEach((plugin_param: string) => {\n            const [node_name_id, input_name] = mode_map[plugin_param].split('.')\n            mapPluginInputToComfyInput(\n                plugin_settings,\n                plugin_param,\n                node_name_id,\n                input_name\n            )\n        })\n\n        plugin_settings = await addMissingControlnetSettings(plugin_settings)\n        for (let i = 0; i < 3; ++i) {\n            const unit = plugin_settings['controlnet_units'][i]\n            // one for each controlnet unit\n            Object.keys(controlnet_txt2img_map).forEach(\n                (plugin_param: string) => {\n                    let [node_name_id, input_name] =\n                        controlnet_txt2img_map[plugin_param].split('.')\n                    // if (\n                    //     node_name_id === 'controlnet_image' ||\n                    //     node_name_id === 'controlnet_mask'\n                    // ) {\n                    //     // the input images and masks are each in separate nodes\n                    //     node_name_id = `${node_name_id}_${i + 1}` //ex: 'controlnet_image.image' -> controlnet_image_1.image\n                    // } else {\n                    //     //all other inputs present in the controlnet script\n                    //     input_name = `${input_name}_${i + 1}` //ex: preprocessor_name -> preprocessor_name_1\n                    // }\n                    input_name = `${input_name}_${i + 1}` //ex: preprocessor_name -> preprocessor_name_1\n\n                    mapPluginInputToComfyInput(\n                        unit,\n                        plugin_param,\n                        node_name_id,\n                        input_name\n                    )\n                }\n            )\n        }\n    } catch (e) {\n        console.error(e)\n    }\n    return prompt\n}\n\nasync function generateComfyMode(\n    nodes: any[],\n    api_prompt: Record<string, any>,\n    plugin_settings: Record<string, any>,\n    mode_map: Record<string, string>\n): Promise<{ image_base64_list: string[]; image_url_list: string[] }> {\n    let image_url_list: string[] = []\n    let image_base64_list: string[] = []\n    try {\n        // const controlnet_settings =\n        //     mapPluginSettingsToControlNet(plugin_settings)\n\n        // console.log('controlnet_settings:', controlnet_settings)\n        const prompt = await mapPluginSettingsToComfyuiPrompt(\n            nodes,\n            copyJson(api_prompt),\n            plugin_settings,\n            mode_map\n        )\n        const final_prompt = copyJson(prompt)\n        if (!plugin_settings['enable_hr']) {\n            //get node_id\n            const hire_output_node = getNodeByNameId(nodes, 'hires_output')\n\n            delete final_prompt[hire_output_node.id]\n        }\n\n        const separated_output_node_ids: string[] = []\n        const node_id_to_controlnet_unit_index: Record<string, number> = {}\n        for (const [index, unit] of plugin_settings[\n            'controlnet_units'\n        ].entries()) {\n            const node_name_id = `preprocessor_output_${index + 1}`\n            const node = getNodeByNameId(nodes, node_name_id)\n            const node_id = node.id.toString()\n            node_id_to_controlnet_unit_index[node_id] = index\n\n            if (unit['comfy_enabled'] === 'disable') {\n                mutePromptNode(nodes, final_prompt, node_name_id)\n            } else if (unit['comfy_enabled'] === 'enable') {\n                separated_output_node_ids.push(node_id)\n            }\n        }\n        // for (let i = 0; i < 3; ++i) {\n        //     const unit = plugin_settings['controlnet_units'][i]\n        //     if (unit['input_image'] === '') {\n        //         mutePromptNode(nodes, final_prompt, `controlnet_image_${i + 1}`)\n        //     }\n        //     if (unit['mask'] === '') {\n        //         mutePromptNode(nodes, final_prompt, `controlnet_mask_${i + 1}`)\n        //     }\n        // }\n        console.log('final_prompt: ', final_prompt)\n        try {\n            var { outputs, separated_outputs } =\n                await comfyui_util.postPromptAndGetBase64JsonResult(\n                    final_prompt,\n                    separated_output_node_ids\n                )\n        } catch (e) {\n            outputs = undefined\n            separated_outputs = undefined\n        }\n        if (outputs) {\n            image_url_list = Object.values(outputs).flat()\n            image_base64_list = image_url_list.map((image_url) => {\n                return base64UrlToBase64(image_url)\n            })\n        }\n        if (separated_outputs) {\n            Object.entries(separated_outputs).forEach(([node_id, images]) => {\n                const controlnet_unit_index =\n                    node_id_to_controlnet_unit_index[node_id]\n                setControlDetectMapSrc(\n                    base64UrlToBase64(images[0]),\n                    controlnet_unit_index\n                )\n            })\n        }\n    } catch (e) {\n        console.error(e)\n    }\n    return { image_base64_list, image_url_list }\n}\nasync function generateComfyTxt2Img(\n    plugin_settings: any\n): Promise<{ image_base64_list: string[]; image_url_list: string[] }> {\n    return generateComfyMode(\n        txt2img.nodes,\n        txt2img_api,\n        plugin_settings,\n        txt2img_map\n    )\n}\nasync function generateComfyImg2Img(\n    plugin_settings: any\n): Promise<{ image_base64_list: string[]; image_url_list: string[] }> {\n    return generateComfyMode(\n        img2img.nodes,\n        img2img_api,\n        plugin_settings,\n        img2img_map\n    )\n}\nasync function generateComfyInpaint(\n    plugin_settings: any\n): Promise<{ image_base64_list: string[]; image_url_list: string[] }> {\n    if ('inpainting_fill' in plugin_settings) {\n        const index = plugin_settings['inpainting_fill']\n        const content_mask_option = [\n            'fill',\n            'original',\n            'latent_noise',\n            'latent_nothing',\n        ]\n        plugin_settings['comfy_content_mask'] = content_mask_option[index]\n\n        // const content_mask = [\n        //     ['fill', ''],\n        //     ['original', 'content_mask_original_output'],\n        //     ['latent_noise', 'content_mask_latent_noise_output'],\n        //     ['latent_nothing', 'content_mask_latent_nothing_output'],\n        // ]\n\n        // const comfy_node_name_id = content_mask[index][1]\n        // const content_mask_node = getNodeByNameId(\n        //     inpaint.nodes,\n        //     comfy_node_name_id\n        // )\n\n        // if (index > 0 && index <= 3 && content_mask_node) {\n        //     plugin_settings['comfy_content_mask'] = [\n        //         content_mask_node.id.toString(),\n        //         0,\n        //     ]\n        // }\n    }\n    return generateComfyMode(\n        inpaint.nodes,\n        inpaint_api,\n        plugin_settings,\n        inpaint_map\n    )\n}\n\nexport default {\n    parseMetadata,\n    getNode,\n    getInput,\n    getLink,\n    getNodesFromLink,\n    getNodeByNameId,\n    mapPluginSettingsToComfyuiPrompt,\n    getPromptNodeByNameId,\n    setInputValue,\n    addMissingSettings,\n    generateComfyTxt2Img,\n    generateComfyImg2Img,\n    generateComfyInpaint,\n    txt2img,\n    txt2img_api,\n    img2img,\n    img2img_api,\n    inpaint,\n    inpaint_api,\n}\n"
  },
  {
    "path": "typescripts/comfyui/native_workflows/IPAdapter_simple_api.json",
    "content": "{\n  \"8\": {\n    \"inputs\": {\n      \"samples\": [\n        \"50\",\n        0\n      ],\n      \"vae\": [\n        \"32\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"14\": {\n    \"inputs\": {\n      \"ckpt_name\": \"dreamshaper_8.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"50\": {\n    \"inputs\": {\n      \"add_noise\": \"enable\",\n      \"noise_seed\": 538408362410054,\n      \"steps\": 30,\n      \"cfg\": 7,\n      \"sampler_name\": \"dpmpp_2m\",\n      \"scheduler\": \"karras\",\n      \"start_at_step\": 0,\n      \"end_at_step\": 10000,\n      \"return_with_leftover_noise\": \"disable\",\n      \"model\": [\n        \"210\",\n        0\n      ],\n      \"positive\": [\n        \"211\",\n        0\n      ],\n      \"negative\": [\n        \"212\",\n        0\n      ],\n      \"latent_image\": [\n        \"95\",\n        0\n      ]\n    },\n    \"class_type\": \"KSamplerAdvanced\"\n  },\n  \"95\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"192\": {\n    \"inputs\": {\n      \"images\": [\n        \"8\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"204\": {\n    \"inputs\": {\n      \"weight\": 0.5,\n      \"noise\": 0.33,\n      \"weight_type\": \"original\",\n      \"start_at\": 0,\n      \"end_at\": 1,\n      \"ipadapter\": [\n        \"205\",\n        0\n      ],\n      \"clip_vision\": [\n        \"206\",\n        0\n      ],\n      \"image\": [\n        \"207\",\n        0\n      ],\n      \"model\": [\n        \"14\",\n        0\n      ]\n    },\n    \"class_type\": \"IPAdapterApply\"\n  },\n  \"205\": {\n    \"inputs\": {\n      \"ipadapter_file\": \"ip-adapter-plus_sd15.bin\"\n    },\n    \"class_type\": \"IPAdapterModelLoader\"\n  },\n  \"206\": {\n    \"inputs\": {\n      \"clip_name\": \"model.safetensors\"\n    },\n    \"class_type\": \"CLIPVisionLoader\"\n  },\n  \"207\": {\n    \"inputs\": {\n      \"interpolation\": \"LANCZOS\",\n      \"crop_position\": \"top\",\n      \"sharpening\": 0.15,\n      \"image\": [\n        \"209\",\n        0\n      ]\n    },\n    \"class_type\": \"PrepImageForClipVision\"\n  },\n  \"209\": {\n    \"inputs\": {\n      \"image\": \"ComfyUI_temp_cqoqp_00001_ (1).png\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"210\": {\n    \"inputs\": {\n      \"block_number\": 3,\n      \"downscale_factor\": 1.5,\n      \"start_percent\": 0,\n      \"end_percent\": 0.45,\n      \"downscale_after_skip\": true,\n      \"downscale_method\": \"bicubic\",\n      \"upscale_method\": \"bicubic\",\n      \"model\": [\n        \"204\",\n        0\n      ]\n    },\n    \"class_type\": \"PatchModelAddDownscale\"\n  },\n  \"211\": {\n    \"inputs\": {\n      \"text\": \"\",\n      \"clip\": [\n        \"14\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"212\": {\n    \"inputs\": {\n      \"text\": \"blurry, low quality\",\n      \"clip\": [\n        \"14\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/IPAdapter_weighted_api.json",
    "content": "{\n  \"1\": {\n    \"inputs\": {\n      \"ckpt_name\": \"dreamshaper_8.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"2\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"3\": {\n    \"inputs\": {\n      \"ipadapter_file\": \"ip-adapter-plus_sd15.bin\"\n    },\n    \"class_type\": \"IPAdapterModelLoader\"\n  },\n  \"4\": {\n    \"inputs\": {\n      \"clip_name\": \"model.safetensors\"\n    },\n    \"class_type\": \"CLIPVisionLoader\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"image\": \"ComfyUI_temp_cqoqp_00001_ (1).png\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"text\": \"beautiful renaissance girl, detailed\",\n      \"clip\": [\n        \"1\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"8\": {\n    \"inputs\": {\n      \"text\": \"blurry, horror\",\n      \"clip\": [\n        \"1\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"9\": {\n    \"inputs\": {\n      \"seed\": 857545940756658,\n      \"steps\": 35,\n      \"cfg\": 5,\n      \"sampler_name\": \"ddim\",\n      \"scheduler\": \"ddim_uniform\",\n      \"denoise\": 1,\n      \"model\": [\n        \"13\",\n        0\n      ],\n      \"positive\": [\n        \"7\",\n        0\n      ],\n      \"negative\": [\n        \"8\",\n        0\n      ],\n      \"latent_image\": [\n        \"10\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"10\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 4\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"11\": {\n    \"inputs\": {\n      \"samples\": [\n        \"9\",\n        0\n      ],\n      \"vae\": [\n        \"2\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"12\": {\n    \"inputs\": {\n      \"filename_prefix\": \"IPAdapter\",\n      \"images\": [\n        \"11\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"13\": {\n    \"inputs\": {\n      \"weight\": 1,\n      \"weight_type\": \"original\",\n      \"start_at\": 0,\n      \"end_at\": 1,\n      \"ipadapter\": [\n        \"3\",\n        0\n      ],\n      \"embeds\": [\n        \"14\",\n        0\n      ],\n      \"model\": [\n        \"1\",\n        0\n      ]\n    },\n    \"class_type\": \"IPAdapterApplyEncoded\"\n  },\n  \"14\": {\n    \"inputs\": {\n      \"ipadapter_plus\": true,\n      \"noise\": 0.31,\n      \"weight_1\": [\n        \"16\",\n        0\n      ],\n      \"weight_2\": [\n        \"17\",\n        0\n      ],\n      \"weight_3\": 1,\n      \"weight_4\": 1,\n      \"clip_vision\": [\n        \"4\",\n        0\n      ],\n      \"image_1\": [\n        \"15\",\n        0\n      ],\n      \"image_2\": [\n        \"6\",\n        0\n      ]\n    },\n    \"class_type\": \"IPAdapterEncoder\"\n  },\n  \"15\": {\n    \"inputs\": {\n      \"image\": \"animation-deku-my-hero-academia.jpg\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"16\": {\n    \"inputs\": {\n      \"Value\": 1\n    },\n    \"class_type\": \"Float\"\n  },\n  \"17\": {\n    \"inputs\": {\n      \"Value\": 0.38\n    },\n    \"class_type\": \"Float\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/animatediff_lcm_api.json",
    "content": "{\n  \"2\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"4\": {\n    \"inputs\": {\n      \"stop_at_clip_layer\": -1,\n      \"clip\": [\n        \"32\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPSetLastLayer\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"text\": \"embedding:BadDream, \",\n      \"clip\": [\n        \"4\",\n        0\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"seed\": 888888891,\n      \"steps\": 8,\n      \"cfg\": 1.5,\n      \"sampler_name\": \"lcm\",\n      \"scheduler\": \"sgm_uniform\",\n      \"denoise\": 1,\n      \"model\": [\n        \"36\",\n        0\n      ],\n      \"positive\": [\n        \"38\",\n        0\n      ],\n      \"negative\": [\n        \"6\",\n        0\n      ],\n      \"latent_image\": [\n        \"9\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"9\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 110\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"10\": {\n    \"inputs\": {\n      \"samples\": [\n        \"7\",\n        0\n      ],\n      \"vae\": [\n        \"2\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"ckpt_name\": \"dreamshaper_8.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"33\": {\n    \"inputs\": {\n      \"context_length\": 16,\n      \"context_stride\": 1,\n      \"context_overlap\": 4,\n      \"context_schedule\": \"uniform\",\n      \"closed_loop\": false\n    },\n    \"class_type\": \"ADE_AnimateDiffUniformContextOptions\"\n  },\n  \"36\": {\n    \"inputs\": {\n      \"model_name\": \"mm_sd_v15_v2.ckpt\",\n      \"beta_schedule\": \"sqrt_linear (AnimateDiff)\",\n      \"motion_scale\": 1,\n      \"apply_v2_models_properly\": false,\n      \"model\": [\n        \"42\",\n        0\n      ],\n      \"context_options\": [\n        \"33\",\n        0\n      ]\n    },\n    \"class_type\": \"ADE_AnimateDiffLoaderWithContext\"\n  },\n  \"37\": {\n    \"inputs\": {\n      \"frame_rate\": 8,\n      \"loop_count\": 0,\n      \"filename_prefix\": \"aaa_readme\",\n      \"format\": \"image/gif\",\n      \"pingpong\": false,\n      \"save_image\": true,\n      \"crf\": 20,\n      \"save_metadata\": true,\n      \"videopreview\": {\n        \"hidden\": false,\n        \"paused\": false,\n        \"params\": {\n          \"filename\": \"aaa_readme_00024.gif\",\n          \"subfolder\": \"\",\n          \"type\": \"output\",\n          \"format\": \"image/gif\"\n        }\n      },\n      \"images\": [\n        \"10\",\n        0\n      ]\n    },\n    \"class_type\": \"VHS_VideoCombine\"\n  },\n  \"38\": {\n    \"inputs\": {\n      \"text\": \"\\\"0\\\" : \\\"Spring, flowers, smile\\\",\\n\\\"20\\\" : \\\"Spring, flowers, smile\\\",\\n\\\"30\\\" : \\\"Summer, sun, happy, windy\\\",\\n\\\"50\\\" : \\\"Summer, sun, happy, windy\\\",\\n\\\"60\\\" : \\\"Autumn, yellow leaves, laugh\\\",\\n\\\"80\\\" : \\\"Autumn, yellow leaves, laugh\\\",\\n\\\"90\\\" : \\\"Winter, wind, snow, smile, seductive\\\",\\n\\\"110\\\" : \\\"Winter, wind snow, smile, seductive\\\"\",\n      \"max_frames\": 110,\n      \"print_output\": false,\n      \"pre_text\": \"25 year old woman, t-shirt\",\n      \"app_text\": \"\",\n      \"start_frame\": 0,\n      \"pw_a\": 0,\n      \"pw_b\": 0,\n      \"pw_c\": 0,\n      \"pw_d\": 0,\n      \"clip\": [\n        \"4\",\n        0\n      ]\n    },\n    \"class_type\": \"BatchPromptSchedule\"\n  },\n  \"41\": {\n    \"inputs\": {\n      \"lora_name\": \"lcm_lora_sd15.safetensors\",\n      \"strength_model\": 1,\n      \"strength_clip\": 1,\n      \"model\": [\n        \"32\",\n        0\n      ],\n      \"clip\": [\n        \"32\",\n        1\n      ]\n    },\n    \"class_type\": \"LoraLoader\"\n  },\n  \"42\": {\n    \"inputs\": {\n      \"sampling\": \"lcm\",\n      \"zsnr\": false,\n      \"model\": [\n        \"41\",\n        0\n      ]\n    },\n    \"class_type\": \"ModelSamplingDiscrete\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/animatediff_simple_api.json",
    "content": "{\n  \"2\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"3\": {\n    \"inputs\": {\n      \"text\": \"girl astronaut walking on the moon. \",\n      \"clip\": [\n        \"4\",\n        0\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"4\": {\n    \"inputs\": {\n      \"stop_at_clip_layer\": -2,\n      \"clip\": [\n        \"32\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPSetLastLayer\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"text\": \"(worst quality, low quality: 1.4)\",\n      \"clip\": [\n        \"4\",\n        0\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"seed\": 888888889,\n      \"steps\": 20,\n      \"cfg\": 8,\n      \"sampler_name\": \"euler\",\n      \"scheduler\": \"normal\",\n      \"denoise\": 1,\n      \"model\": [\n        \"27\",\n        0\n      ],\n      \"positive\": [\n        \"3\",\n        0\n      ],\n      \"negative\": [\n        \"6\",\n        0\n      ],\n      \"latent_image\": [\n        \"9\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"9\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 16\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"10\": {\n    \"inputs\": {\n      \"samples\": [\n        \"7\",\n        0\n      ],\n      \"vae\": [\n        \"2\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"27\": {\n    \"inputs\": {\n      \"model_name\": \"mm_sd_v14.ckpt\",\n      \"beta_schedule\": \"sqrt_linear (AnimateDiff)\",\n      \"motion_scale\": 1,\n      \"apply_v2_models_properly\": false,\n      \"model\": [\n        \"32\",\n        0\n      ]\n    },\n    \"class_type\": \"ADE_AnimateDiffLoaderWithContext\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"ckpt_name\": \"cardosAnime_v20.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"35\": {\n    \"inputs\": {\n      \"frame_rate\": 8,\n      \"loop_count\": 0,\n      \"filename_prefix\": \"aaa_readme\",\n      \"format\": \"image/gif\",\n      \"pingpong\": false,\n      \"save_image\": true,\n      \"crf\": 20,\n      \"save_metadata\": false,\n      \"videopreview\": {\n        \"hidden\": false,\n        \"paused\": false,\n        \"params\": {\n          \"filename\": \"aaa_readme_00022.gif\",\n          \"subfolder\": \"\",\n          \"type\": \"output\",\n          \"format\": \"image/gif\"\n        }\n      },\n      \"images\": [\n        \"10\",\n        0\n      ]\n    },\n    \"class_type\": \"VHS_VideoCombine\"\n  },\n  \"37\": {\n    \"inputs\": {\n      \"images\": [\n        \"10\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/real_time_lcm_img2img_api.json",
    "content": "{\n  \"6\": {\n    \"inputs\": {\n      \"text\": \"cute girl\",\n      \"clip\": [\n        \"38\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"20\": {\n    \"inputs\": {\n      \"ckpt_name\": \"aniverse_v15Pruned.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"30\": {\n    \"inputs\": {\n      \"seed\": 951163705423093,\n      \"steps\": 4,\n      \"cfg\": 1,\n      \"sampler_name\": \"lcm\",\n      \"scheduler\": \"sgm_uniform\",\n      \"denoise\": 0.5,\n      \"model\": [\n        \"38\",\n        0\n      ],\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"36\",\n        0\n      ],\n      \"latent_image\": [\n        \"40\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"31\": {\n    \"inputs\": {\n      \"samples\": [\n        \"30\",\n        0\n      ],\n      \"vae\": [\n        \"20\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"images\": [\n        \"31\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"36\": {\n    \"inputs\": {\n      \"text\": \"\",\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"38\": {\n    \"inputs\": {\n      \"lora_name\": \"lcm_lora_sd15.safetensors\",\n      \"strength_model\": 1,\n      \"strength_clip\": 1,\n      \"model\": [\n        \"20\",\n        0\n      ],\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"Load Lora\"\n  },\n  \"39\": {\n    \"inputs\": {\n      \"image\": \"output_image.png.png\",\n      \"upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"40\": {\n    \"inputs\": {\n      \"pixels\": [\n        \"41\",\n        0\n      ],\n      \"vae\": [\n        \"20\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEEncode\"\n  },\n  \"41\": {\n    \"inputs\": {\n      \"side_length\": 512,\n      \"side\": \"Longest\",\n      \"upscale_method\": \"nearest-exact\",\n      \"crop\": \"disabled\",\n      \"image\": [\n        \"39\",\n        0\n      ]\n    },\n    \"class_type\": \"Image scale to side\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/real_time_lcm_sketching_api.json",
    "content": "{\n  \"6\": {\n    \"inputs\": {\n      \"text\": \"\",\n      \"clip\": [\n        \"38\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"20\": {\n    \"inputs\": {\n      \"ckpt_name\": \"aniverse_v15Pruned.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"30\": {\n    \"inputs\": {\n      \"seed\": [\n        \"70\",\n        0\n      ],\n      \"steps\": 4,\n      \"cfg\": 1,\n      \"sampler_name\": \"lcm\",\n      \"scheduler\": \"sgm_uniform\",\n      \"denoise\": 1,\n      \"model\": [\n        \"38\",\n        0\n      ],\n      \"positive\": [\n        \"74\",\n        1\n      ],\n      \"negative\": [\n        \"74\",\n        2\n      ],\n      \"latent_image\": [\n        \"46\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"31\": {\n    \"inputs\": {\n      \"samples\": [\n        \"30\",\n        0\n      ],\n      \"vae\": [\n        \"20\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"images\": [\n        \"31\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"36\": {\n    \"inputs\": {\n      \"text\": \"(nsfw:1.2), (nude:1.2)\",\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"38\": {\n    \"inputs\": {\n      \"lora_name\": \"lcm_lora_sd15.safetensors\",\n      \"strength_model\": 1,\n      \"strength_clip\": 1,\n      \"model\": [\n        \"20\",\n        0\n      ],\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"Load Lora\"\n  },\n  \"46\": {\n    \"inputs\": {\n      \"width\": [\n        \"51\",\n        0\n      ],\n      \"height\": [\n        \"51\",\n        1\n      ],\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"47\": {\n    \"inputs\": {\n      \"image\": \"pasted/image (14).png\",\n      \"upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"51\": {\n    \"inputs\": {\n      \"image\": [\n        \"53\",\n        0\n      ]\n    },\n    \"class_type\": \"Get image size\"\n  },\n  \"53\": {\n    \"inputs\": {\n      \"side_length\": [\n        \"57\",\n        0\n      ],\n      \"side\": \"Longest\",\n      \"upscale_method\": \"nearest-exact\",\n      \"crop\": \"disabled\",\n      \"image\": [\n        \"73\",\n        0\n      ]\n    },\n    \"class_type\": \"Image scale to side\"\n  },\n  \"57\": {\n    \"inputs\": {\n      \"Value\": 512\n    },\n    \"class_type\": \"Integer\"\n  },\n  \"59\": {\n    \"inputs\": {\n      \"seed\": [\n        \"70\",\n        0\n      ],\n      \"steps\": 8,\n      \"cfg\": 1,\n      \"sampler_name\": \"lcm\",\n      \"scheduler\": \"sgm_uniform\",\n      \"denoise\": 0.5,\n      \"model\": [\n        \"38\",\n        0\n      ],\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"36\",\n        0\n      ],\n      \"latent_image\": [\n        \"65\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"63\": {\n    \"inputs\": {\n      \"samples\": [\n        \"59\",\n        0\n      ],\n      \"vae\": [\n        \"20\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"64\": {\n    \"inputs\": {\n      \"images\": [\n        \"63\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"65\": {\n    \"inputs\": {\n      \"upscale_method\": \"nearest-exact\",\n      \"scale_by\": 1.5,\n      \"samples\": [\n        \"30\",\n        0\n      ]\n    },\n    \"class_type\": \"LatentUpscaleBy\"\n  },\n  \"70\": {\n    \"inputs\": {\n      \"seed\": 412914567948332\n    },\n    \"class_type\": \"APS_Seed\"\n  },\n  \"73\": {\n    \"inputs\": {\n      \"image\": [\n        \"47\",\n        0\n      ]\n    },\n    \"class_type\": \"ImageInvert\"\n  },\n  \"74\": {\n    \"inputs\": {\n      \"preprocessor_name\": \"ScribblePreprocessor\",\n      \"control_net_name\": \"control_lora_rank128_v11p_sd15_scribble_fp16.safetensors\",\n      \"strength\": 1,\n      \"start_percent\": 0,\n      \"end_percent\": 1,\n      \"resolution\": [\n        \"57\",\n        0\n      ],\n      \"threshold_a\": 0,\n      \"threshold_b\": 0,\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"36\",\n        0\n      ],\n      \"image\": [\n        \"53\",\n        0\n      ]\n    },\n    \"class_type\": \"ControlnetUnit\"\n  },\n  \"75\": {\n    \"inputs\": {\n      \"images\": [\n        \"74\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/real_time_lcm_txt2img_api.json",
    "content": "{\n  \"6\": {\n    \"inputs\": {\n      \"text\": \"cute girl\",\n      \"clip\": [\n        \"38\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"20\": {\n    \"inputs\": {\n      \"ckpt_name\": \"aniverse_v15Pruned.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"30\": {\n    \"inputs\": {\n      \"seed\": 951163705423093,\n      \"steps\": 4,\n      \"cfg\": 1,\n      \"sampler_name\": \"lcm\",\n      \"scheduler\": \"sgm_uniform\",\n      \"denoise\": 1,\n      \"model\": [\n        \"38\",\n        0\n      ],\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"36\",\n        0\n      ],\n      \"latent_image\": [\n        \"37\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"31\": {\n    \"inputs\": {\n      \"samples\": [\n        \"30\",\n        0\n      ],\n      \"vae\": [\n        \"20\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"images\": [\n        \"31\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"36\": {\n    \"inputs\": {\n      \"text\": \"\",\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"37\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"38\": {\n    \"inputs\": {\n      \"lora_name\": \"lcm_lora_sd15.safetensors\",\n      \"strength_model\": 1,\n      \"strength_clip\": 1,\n      \"model\": [\n        \"20\",\n        0\n      ],\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"Load Lora\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/sdxl_turbo_txt2img_api.json",
    "content": "{\n  \"5\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"text\": \"beautiful landscape scenery glass bottle with a galaxy inside cute fennec fox snow HDR sunset\",\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"text\": \"text, watermark\",\n      \"clip\": [\n        \"20\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"8\": {\n    \"inputs\": {\n      \"samples\": [\n        \"13\",\n        0\n      ],\n      \"vae\": [\n        \"20\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"13\": {\n    \"inputs\": {\n      \"add_noise\": true,\n      \"noise_seed\": 0,\n      \"cfg\": 1,\n      \"model\": [\n        \"20\",\n        0\n      ],\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"7\",\n        0\n      ],\n      \"sampler\": [\n        \"14\",\n        0\n      ],\n      \"sigmas\": [\n        \"22\",\n        0\n      ],\n      \"latent_image\": [\n        \"5\",\n        0\n      ]\n    },\n    \"class_type\": \"SamplerCustom\"\n  },\n  \"14\": {\n    \"inputs\": {\n      \"sampler_name\": \"euler_ancestral\"\n    },\n    \"class_type\": \"KSamplerSelect\"\n  },\n  \"20\": {\n    \"inputs\": {\n      \"ckpt_name\": \"sd_xl_turbo_1.0_fp16.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"22\": {\n    \"inputs\": {\n      \"steps\": 1,\n      \"model\": [\n        \"20\",\n        0\n      ]\n    },\n    \"class_type\": \"SDTurboScheduler\"\n  },\n  \"25\": {\n    \"inputs\": {\n      \"images\": [\n        \"8\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/native_workflows/zoom_out_api.json",
    "content": "{\n  \"1\": {\n    \"inputs\": {\n      \"image\": \"000662ed61a84c86fc8a3fe69d38a6e2 (1).jpg\",\n      \"choose file to upload\": \"image\"\n    },\n    \"class_type\": \"LoadImage\"\n  },\n  \"2\": {\n    \"inputs\": {\n      \"left\": 112,\n      \"top\": 112,\n      \"right\": 104,\n      \"bottom\": 208,\n      \"feathering\": 20,\n      \"image\": [\n        \"50\",\n        0\n      ]\n    },\n    \"class_type\": \"ImagePadForOutpaint\"\n  },\n  \"3\": {\n    \"inputs\": {\n      \"images\": [\n        \"2\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"5\": {\n    \"inputs\": {\n      \"width\": [\n        \"12\",\n        2\n      ],\n      \"height\": [\n        \"12\",\n        1\n      ],\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"pixels\": [\n        \"2\",\n        0\n      ],\n      \"vae\": [\n        \"7\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"12\": {\n    \"inputs\": {\n      \"value\": [\n        \"2\",\n        0\n      ]\n    },\n    \"class_type\": \"ImpactImageInfo\"\n  },\n  \"14\": {\n    \"inputs\": {\n      \"x\": 0,\n      \"y\": 0,\n      \"resize_source\": true,\n      \"destination\": [\n        \"6\",\n        0\n      ],\n      \"source\": [\n        \"5\",\n        0\n      ],\n      \"mask\": [\n        \"2\",\n        1\n      ]\n    },\n    \"class_type\": \"LatentCompositeMasked\"\n  },\n  \"15\": {\n    \"inputs\": {\n      \"samples\": [\n        \"14\",\n        0\n      ],\n      \"vae\": [\n        \"7\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"19\": {\n    \"inputs\": {\n      \"images\": [\n        \"15\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"20\": {\n    \"inputs\": {\n      \"strength\": 1,\n      \"conditioning\": [\n        \"27\",\n        4\n      ],\n      \"control_net\": [\n        \"21\",\n        0\n      ],\n      \"image\": [\n        \"47\",\n        0\n      ]\n    },\n    \"class_type\": \"ControlNetApply\"\n  },\n  \"21\": {\n    \"inputs\": {\n      \"control_net_name\": \"control_v11p_sd15_inpaint_fp16.safetensors\"\n    },\n    \"class_type\": \"ControlNetLoader\"\n  },\n  \"22\": {\n    \"inputs\": {\n      \"ckpt_name\": \"aniverse_v15Pruned.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"23\": {\n    \"inputs\": {\n      \"model\": [\n        \"22\",\n        0\n      ],\n      \"clip\": [\n        \"22\",\n        1\n      ],\n      \"vae\": [\n        \"22\",\n        2\n      ],\n      \"positive\": [\n        \"24\",\n        0\n      ],\n      \"negative\": [\n        \"25\",\n        0\n      ]\n    },\n    \"class_type\": \"ToBasicPipe\"\n  },\n  \"24\": {\n    \"inputs\": {\n      \"text\": \"\",\n      \"clip\": [\n        \"22\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"25\": {\n    \"inputs\": {\n      \"text\": \"nsfw\",\n      \"clip\": [\n        \"22\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"27\": {\n    \"inputs\": {\n      \"basic_pipe\": [\n        \"23\",\n        0\n      ]\n    },\n    \"class_type\": \"FromBasicPipe_v2\"\n  },\n  \"29\": {\n    \"inputs\": {\n      \"basic_pipe\": [\n        \"27\",\n        0\n      ],\n      \"positive\": [\n        \"20\",\n        0\n      ]\n    },\n    \"class_type\": \"EditBasicPipe\"\n  },\n  \"30\": {\n    \"inputs\": {\n      \"seed\": 949895177872699,\n      \"steps\": 20,\n      \"cfg\": 8,\n      \"sampler_name\": \"euler\",\n      \"scheduler\": \"normal\",\n      \"denoise\": 1,\n      \"basic_pipe\": [\n        \"29\",\n        0\n      ],\n      \"latent_image\": [\n        \"62\",\n        0\n      ]\n    },\n    \"class_type\": \"ImpactKSamplerBasicPipe\"\n  },\n  \"31\": {\n    \"inputs\": {\n      \"samples\": [\n        \"30\",\n        1\n      ],\n      \"vae\": [\n        \"30\",\n        2\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"32\": {\n    \"inputs\": {\n      \"images\": [\n        \"31\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"33\": {\n    \"inputs\": {\n      \"samples\": [\n        \"14\",\n        0\n      ],\n      \"mask\": [\n        \"2\",\n        1\n      ]\n    },\n    \"class_type\": \"SetLatentNoiseMask\"\n  },\n  \"47\": {\n    \"inputs\": {\n      \"image\": [\n        \"2\",\n        0\n      ],\n      \"mask\": [\n        \"2\",\n        1\n      ]\n    },\n    \"class_type\": \"InpaintPreprocessor\"\n  },\n  \"50\": {\n    \"inputs\": {\n      \"upscale_method\": \"nearest-exact\",\n      \"scale_by\": 0.3,\n      \"image\": [\n        \"1\",\n        0\n      ]\n    },\n    \"class_type\": \"ImageScaleBy\"\n  },\n  \"52\": {\n    \"inputs\": {\n      \"clip_vision\": [\n        \"53\",\n        0\n      ],\n      \"image\": [\n        \"1\",\n        0\n      ]\n    },\n    \"class_type\": \"CLIPVisionEncode\"\n  },\n  \"53\": {\n    \"inputs\": {\n      \"clip_name\": \"SD1.5/pytorch_model.bin\"\n    },\n    \"class_type\": \"CLIPVisionLoader\"\n  },\n  \"56\": {\n    \"inputs\": {\n      \"pixels\": [\n        \"2\",\n        0\n      ],\n      \"vae\": [\n        \"7\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEEncode\"\n  },\n  \"62\": {\n    \"inputs\": {\n      \"amount\": 2,\n      \"samples\": [\n        \"33\",\n        0\n      ]\n    },\n    \"class_type\": \"RepeatLatentBatch\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/txt2img_api.json",
    "content": "{\n  \"3\": {\n    \"inputs\": {\n      \"seed\": 945794611996037,\n      \"steps\": 12,\n      \"cfg\": 8,\n      \"sampler_name\": \"dpmpp_sde\",\n      \"scheduler\": \"normal\",\n      \"denoise\": 1,\n      \"model\": [\n        \"58\",\n        0\n      ],\n      \"positive\": [\n        \"81\",\n        3\n      ],\n      \"negative\": [\n        \"81\",\n        4\n      ],\n      \"latent_image\": [\n        \"5\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"5\": {\n    \"inputs\": {\n      \"width\": 512,\n      \"height\": 512,\n      \"batch_size\": 1\n    },\n    \"class_type\": \"EmptyLatentImage\"\n  },\n  \"6\": {\n    \"inputs\": {\n      \"text\": [\n        \"58\",\n        2\n      ],\n      \"clip\": [\n        \"58\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"7\": {\n    \"inputs\": {\n      \"text\": [\n        \"60\",\n        2\n      ],\n      \"clip\": [\n        \"60\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPTextEncode\"\n  },\n  \"8\": {\n    \"inputs\": {\n      \"samples\": [\n        \"3\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"9\": {\n    \"inputs\": {\n      \"filename_prefix\": \"ComfyUI\",\n      \"images\": [\n        \"8\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"11\": {\n    \"inputs\": {\n      \"seed\": 702670332387358,\n      \"steps\": 14,\n      \"cfg\": 8,\n      \"sampler_name\": \"dpmpp_2m\",\n      \"scheduler\": \"simple\",\n      \"denoise\": 0.5,\n      \"model\": [\n        \"58\",\n        0\n      ],\n      \"positive\": [\n        \"81\",\n        3\n      ],\n      \"negative\": [\n        \"81\",\n        4\n      ],\n      \"latent_image\": [\n        \"55\",\n        0\n      ]\n    },\n    \"class_type\": \"KSampler\"\n  },\n  \"12\": {\n    \"inputs\": {\n      \"filename_prefix\": \"ComfyUI\",\n      \"images\": [\n        \"13\",\n        0\n      ]\n    },\n    \"class_type\": \"SaveImage\"\n  },\n  \"13\": {\n    \"inputs\": {\n      \"samples\": [\n        \"11\",\n        0\n      ],\n      \"vae\": [\n        \"57\",\n        0\n      ]\n    },\n    \"class_type\": \"VAEDecode\"\n  },\n  \"16\": {\n    \"inputs\": {\n      \"ckpt_name\": \"dreamshaper_8.safetensors\"\n    },\n    \"class_type\": \"CheckpointLoaderSimple\"\n  },\n  \"55\": {\n    \"inputs\": {\n      \"upscale_method\": \"nearest-exact\",\n      \"scale_by\": 2,\n      \"samples\": [\n        \"3\",\n        0\n      ]\n    },\n    \"class_type\": \"LatentUpscaleBy\"\n  },\n  \"57\": {\n    \"inputs\": {\n      \"vae_name\": \"vae-ft-mse-840000-ema-pruned.safetensors\"\n    },\n    \"class_type\": \"VAELoader\"\n  },\n  \"58\": {\n    \"inputs\": {\n      \"prompt\": \"<lora:lora_delta_small:0.7> lora_delta girl lora_bright_style girl masterpiece HDR victorian portrait painting of woman, blonde hair, mountain nature, blue sky\",\n      \"model\": [\n        \"60\",\n        0\n      ],\n      \"clip\": [\n        \"98\",\n        0\n      ]\n    },\n    \"class_type\": \"LoadLorasFromPrompt\"\n  },\n  \"60\": {\n    \"inputs\": {\n      \"prompt\": \"bad hands, text, watermark\",\n      \"model\": [\n        \"16\",\n        0\n      ],\n      \"clip\": [\n        \"98\",\n        0\n      ]\n    },\n    \"class_type\": \"LoadLorasFromPrompt\"\n  },\n  \"81\": {\n    \"inputs\": {\n      \"is_enabled_1\": \"disable\",\n      \"preprocessor_name_1\": \"CannyEdgePreprocessor\",\n      \"control_net_name_1\": \"control_lora_rank128_v11p_sd15_canny_fp16.safetensors\",\n      \"strength_1\": 1,\n      \"threshold_a_1\": 100,\n      \"threshold_b_1\": 200,\n      \"start_percent_1\": 0,\n      \"end_percent_1\": 1,\n      \"resolution_1\": 512,\n      \"is_enabled_2\": \"disable\",\n      \"preprocessor_name_2\": \"OpenposePreprocessor\",\n      \"control_net_name_2\": \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n      \"strength_2\": 1,\n      \"threshold_a_2\": 0,\n      \"threshold_b_2\": 0,\n      \"start_percent_2\": 0,\n      \"end_percent_2\": 1,\n      \"resolution_2\": 512,\n      \"is_enabled_3\": \"disable\",\n      \"preprocessor_name_3\": \"InpaintPreprocessor\",\n      \"control_net_name_3\": \"control_lora_rank128_v11p_sd15_inpaint_fp16.safetensors\",\n      \"strength_3\": 1,\n      \"threshold_a_3\": 0,\n      \"threshold_b_3\": 0,\n      \"start_percent_3\": 0,\n      \"end_percent_3\": 1,\n      \"resolution_3\": 512,\n      \"positive\": [\n        \"6\",\n        0\n      ],\n      \"negative\": [\n        \"7\",\n        0\n      ]\n    },\n    \"class_type\": \"ControlNetScript\"\n  },\n  \"91\": {\n    \"inputs\": {\n      \"images\": [\n        \"81\",\n        0\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"92\": {\n    \"inputs\": {\n      \"images\": [\n        \"81\",\n        1\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"93\": {\n    \"inputs\": {\n      \"images\": [\n        \"81\",\n        2\n      ]\n    },\n    \"class_type\": \"PreviewImage\"\n  },\n  \"98\": {\n    \"inputs\": {\n      \"stop_at_clip_layer\": -1,\n      \"clip\": [\n        \"16\",\n        1\n      ]\n    },\n    \"class_type\": \"CLIPSetLastLayer\"\n  }\n}"
  },
  {
    "path": "typescripts/comfyui/txt2img_workflow.json",
    "content": "{\n  \"last_node_id\": 98,\n  \"last_link_id\": 156,\n  \"nodes\": [\n    {\n      \"id\": 8,\n      \"type\": \"VAEDecode\",\n      \"pos\": [\n        1238.8565730529783,\n        603.497425166778\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 23,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 36\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 82\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            9\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEDecode\"\n      }\n    },\n    {\n      \"id\": 55,\n      \"type\": \"LatentUpscaleBy\",\n      \"pos\": [\n        1465,\n        -133\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 82\n      },\n      \"flags\": {},\n      \"order\": 24,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 78\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            79\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Upscale Latent By | id:scaler\",\n      \"properties\": {\n        \"Node name for S&R\": \"LatentUpscaleBy\"\n      },\n      \"widgets_values\": [\n        \"nearest-exact\",\n        2\n      ]\n    },\n    {\n      \"id\": 13,\n      \"type\": \"VAEDecode\",\n      \"pos\": [\n        1961,\n        125\n      ],\n      \"size\": {\n        \"0\": 210,\n        \"1\": 46\n      },\n      \"flags\": {},\n      \"order\": 27,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"samples\",\n          \"type\": \"LATENT\",\n          \"link\": 15\n        },\n        {\n          \"name\": \"vae\",\n          \"type\": \"VAE\",\n          \"link\": 83\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            17\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"Node name for S&R\": \"VAEDecode\"\n      }\n    },\n    {\n      \"id\": 57,\n      \"type\": \"VAELoader\",\n      \"pos\": [\n        -1483,\n        541\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 0,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            81\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Load VAE | id:vae\",\n      \"properties\": {\n        \"Node name for S&R\": \"VAELoader\"\n      },\n      \"widgets_values\": [\n        \"vae-ft-mse-840000-ema-pruned.safetensors\"\n      ]\n    },\n    {\n      \"id\": 56,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        -740,\n        606\n      ],\n      \"size\": [\n        75,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 9,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 81\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [\n            82,\n            83\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 59,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        -730,\n        533\n      ],\n      \"size\": [\n        82,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 10,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 89\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            90\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 63,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        663,\n        -211\n      ],\n      \"size\": [\n        140.8,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 21,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 136\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            105,\n            107\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 7,\n      \"type\": \"CLIPTextEncode\",\n      \"pos\": [\n        451,\n        493\n      ],\n      \"size\": {\n        \"0\": 425.27801513671875,\n        \"1\": 180.6060791015625\n      },\n      \"flags\": {},\n      \"order\": 14,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 119\n        },\n        {\n          \"name\": \"text\",\n          \"type\": \"STRING\",\n          \"link\": 98,\n          \"widget\": {\n            \"name\": \"text\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            140\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Text Encode (Prompt) | id:negative_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPTextEncode\"\n      },\n      \"widgets_values\": [\n        \"\"\n      ]\n    },\n    {\n      \"id\": 3,\n      \"type\": \"KSampler\",\n      \"pos\": [\n        1190,\n        -515\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 262\n      },\n      \"flags\": {},\n      \"order\": 22,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 93\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 106\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 105\n        },\n        {\n          \"name\": \"latent_image\",\n          \"type\": \"LATENT\",\n          \"link\": 39\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            36,\n            78\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"KSampler | id:sampler\",\n      \"properties\": {\n        \"Node name for S&R\": \"KSampler\"\n      },\n      \"widgets_values\": [\n        945794611996037,\n        \"fixed\",\n        12,\n        8,\n        \"dpmpp_sde\",\n        \"normal\",\n        1\n      ]\n    },\n    {\n      \"id\": 12,\n      \"type\": \"SaveImage\",\n      \"pos\": [\n        2240,\n        123\n      ],\n      \"size\": {\n        \"0\": 407.53717041015625,\n        \"1\": 468.13226318359375\n      },\n      \"flags\": {},\n      \"order\": 28,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 17\n        }\n      ],\n      \"title\": \"Save Image | id:hires_output\",\n      \"properties\": {},\n      \"widgets_values\": [\n        \"ComfyUI\"\n      ]\n    },\n    {\n      \"id\": 62,\n      \"type\": \"Reroute\",\n      \"pos\": [\n        689,\n        -612\n      ],\n      \"size\": [\n        140.8,\n        26\n      ],\n      \"flags\": {},\n      \"order\": 20,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"\",\n          \"type\": \"*\",\n          \"link\": 135\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            106,\n            108\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"properties\": {\n        \"showOutputText\": true,\n        \"horizontal\": false\n      }\n    },\n    {\n      \"id\": 6,\n      \"type\": \"CLIPTextEncode\",\n      \"pos\": [\n        464,\n        250\n      ],\n      \"size\": {\n        \"0\": 422.84503173828125,\n        \"1\": 164.31304931640625\n      },\n      \"flags\": {},\n      \"order\": 15,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 87\n        },\n        {\n          \"name\": \"text\",\n          \"type\": \"STRING\",\n          \"link\": 88,\n          \"widget\": {\n            \"name\": \"text\"\n          }\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CONDITIONING\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            131\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Text Encode (Prompt) | id:positive_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPTextEncode\"\n      },\n      \"widgets_values\": [\n        \"masterpiece HDR victorian portrait painting of woman, blonde hair, mountain nature, blue sky\\n\"\n      ]\n    },\n    {\n      \"id\": 11,\n      \"type\": \"KSampler\",\n      \"pos\": [\n        1570,\n        130\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 262\n      },\n      \"flags\": {},\n      \"order\": 26,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 97,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 108,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 107,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"latent_image\",\n          \"type\": \"LATENT\",\n          \"link\": 79,\n          \"slot_index\": 3\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            15\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"KSampler | id:hires_sampler\",\n      \"properties\": {\n        \"Node name for S&R\": \"KSampler\"\n      },\n      \"widgets_values\": [\n        702670332387358,\n        \"fixed\",\n        14,\n        8,\n        \"dpmpp_2m\",\n        \"simple\",\n        0.5\n      ]\n    },\n    {\n      \"id\": 58,\n      \"type\": \"LoadLorasFromPrompt\",\n      \"pos\": [\n        -696,\n        175\n      ],\n      \"size\": {\n        \"0\": 462,\n        \"1\": 200\n      },\n      \"flags\": {},\n      \"order\": 13,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 94\n        },\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 155\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            93,\n            97\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            87\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"STRING\",\n          \"type\": \"STRING\",\n          \"links\": [\n            88\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Loras From Prompt | id:multi_loras_positive_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadLorasFromPrompt\"\n      },\n      \"widgets_values\": [\n        \"<lora:lora_delta_small:0.7> lora_delta girl lora_bright_style girl masterpiece HDR victorian portrait painting of woman, blonde hair, mountain nature, blue sky\"\n      ]\n    },\n    {\n      \"id\": 60,\n      \"type\": \"LoadLorasFromPrompt\",\n      \"pos\": [\n        -78,\n        572\n      ],\n      \"size\": {\n        \"0\": 462,\n        \"1\": 200\n      },\n      \"flags\": {},\n      \"order\": 12,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"MODEL\",\n          \"link\": 90\n        },\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 156\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            94\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            119\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"STRING\",\n          \"type\": \"STRING\",\n          \"links\": [\n            98\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Loras From Prompt | id:multi_loras_negative_prompt\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadLorasFromPrompt\"\n      },\n      \"widgets_values\": [\n        \"bad hands, text, watermark\"\n      ]\n    },\n    {\n      \"id\": 9,\n      \"type\": \"SaveImage\",\n      \"pos\": [\n        1499,\n        603\n      ],\n      \"size\": {\n        \"0\": 232.94032287597656,\n        \"1\": 282.4336242675781\n      },\n      \"flags\": {},\n      \"order\": 25,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 9\n        }\n      ],\n      \"properties\": {},\n      \"widgets_values\": [\n        \"ComfyUI\"\n      ]\n    },\n    {\n      \"id\": 87,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -150,\n        -970\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 140.65826416015625\n      },\n      \"flags\": {},\n      \"order\": 1,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            148\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_mask_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 91,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        790,\n        -1290\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 17,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 151\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 92,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        1150,\n        -1290\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 18,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 152\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 93,\n      \"type\": \"PreviewImage\",\n      \"pos\": [\n        1510,\n        -1290\n      ],\n      \"size\": {\n        \"0\": 336,\n        \"1\": 246\n      },\n      \"flags\": {},\n      \"order\": 19,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"images\",\n          \"type\": \"IMAGE\",\n          \"link\": 153\n        }\n      ],\n      \"title\": \"Preview Image | id:preprocessor_output_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"PreviewImage\"\n      }\n    },\n    {\n      \"id\": 86,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -480,\n        -1490\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 244.3121795654297\n      },\n      \"flags\": {\n        \"collapsed\": false\n      },\n      \"order\": 2,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            146\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_mask_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 5,\n      \"type\": \"EmptyLatentImage\",\n      \"pos\": [\n        811,\n        -775\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 106\n      },\n      \"flags\": {},\n      \"order\": 3,\n      \"mode\": 0,\n      \"inputs\": [],\n      \"outputs\": [\n        {\n          \"name\": \"LATENT\",\n          \"type\": \"LATENT\",\n          \"links\": [\n            39\n          ],\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"Empty Latent Image | id:latent_image\",\n      \"properties\": {\n        \"Node name for S&R\": \"EmptyLatentImage\"\n      },\n      \"widgets_values\": [\n        512,\n        512,\n        1\n      ]\n    },\n    {\n      \"id\": 81,\n      \"type\": \"ControlNetScript\",\n      \"pos\": [\n        242,\n        -1099\n      ],\n      \"size\": {\n        \"0\": 506.0240173339844,\n        \"1\": 822\n      },\n      \"flags\": {},\n      \"order\": 16,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 131\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"link\": 140,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"image_1\",\n          \"type\": \"IMAGE\",\n          \"link\": 137\n        },\n        {\n          \"name\": \"mask_1\",\n          \"type\": \"IMAGE\",\n          \"link\": 146,\n          \"slot_index\": 3\n        },\n        {\n          \"name\": \"image_2\",\n          \"type\": \"IMAGE\",\n          \"link\": 147\n        },\n        {\n          \"name\": \"mask_2\",\n          \"type\": \"IMAGE\",\n          \"link\": 148\n        },\n        {\n          \"name\": \"image_3\",\n          \"type\": \"IMAGE\",\n          \"link\": 150\n        },\n        {\n          \"name\": \"mask_3\",\n          \"type\": \"IMAGE\",\n          \"link\": 149\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"preprocessed_image_1\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            151\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"preprocessed_image_2\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            152\n          ],\n          \"shape\": 3,\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"preprocessed_image_3\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            153\n          ],\n          \"shape\": 3,\n          \"slot_index\": 2\n        },\n        {\n          \"name\": \"positive\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            135\n          ],\n          \"shape\": 3,\n          \"slot_index\": 3\n        },\n        {\n          \"name\": \"negative\",\n          \"type\": \"CONDITIONING\",\n          \"links\": [\n            136\n          ],\n          \"shape\": 3,\n          \"slot_index\": 4\n        }\n      ],\n      \"title\": \"ControlNet Script | id:controlnet_script\",\n      \"properties\": {\n        \"Node name for S&R\": \"ControlNetScript\"\n      },\n      \"widgets_values\": [\n        \"disable\",\n        \"CannyEdgePreprocessor\",\n        \"control_lora_rank128_v11p_sd15_canny_fp16.safetensors\",\n        1,\n        100,\n        200,\n        0,\n        1,\n        512,\n        \"disable\",\n        \"OpenposePreprocessor\",\n        \"control_lora_rank128_v11p_sd15_openpose_fp16.safetensors\",\n        1,\n        0,\n        0,\n        0,\n        1,\n        512,\n        \"disable\",\n        \"InpaintPreprocessor\",\n        \"control_lora_rank128_v11p_sd15_inpaint_fp16.safetensors\",\n        1,\n        0,\n        0,\n        0,\n        1,\n        512\n      ]\n    },\n    {\n      \"id\": 89,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -300,\n        -450\n      ],\n      \"size\": {\n        \"0\": 277.20001220703125,\n        \"1\": 192.7110595703125\n      },\n      \"flags\": {},\n      \"order\": 4,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            149\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_mask_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 90,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -670,\n        -460\n      ],\n      \"size\": {\n        \"0\": 285.6000061035156,\n        \"1\": 213.3619384765625\n      },\n      \"flags\": {},\n      \"order\": 5,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            150\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_image_3\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 88,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -440,\n        -970\n      ],\n      \"size\": {\n        \"0\": 285.6000061035156,\n        \"1\": 163.2183074951172\n      },\n      \"flags\": {},\n      \"order\": 6,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            147\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_image_2\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 64,\n      \"type\": \"LoadImage\",\n      \"pos\": [\n        -830,\n        -1490\n      ],\n      \"size\": {\n        \"0\": 306.4342346191406,\n        \"1\": 230.96018981933594\n      },\n      \"flags\": {\n        \"collapsed\": false\n      },\n      \"order\": 7,\n      \"mode\": 2,\n      \"outputs\": [\n        {\n          \"name\": \"IMAGE\",\n          \"type\": \"IMAGE\",\n          \"links\": [\n            137\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"MASK\",\n          \"type\": \"MASK\",\n          \"links\": null,\n          \"shape\": 3\n        }\n      ],\n      \"title\": \"Load Image | id:controlnet_image_1\",\n      \"properties\": {\n        \"Node name for S&R\": \"LoadImage\"\n      },\n      \"widgets_values\": [\n        \"AnimateDiff_00005_ (1) (2).gif\",\n        \"image\"\n      ]\n    },\n    {\n      \"id\": 16,\n      \"type\": \"CheckpointLoaderSimple\",\n      \"pos\": [\n        -1473,\n        311\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 98\n      },\n      \"flags\": {},\n      \"order\": 8,\n      \"mode\": 0,\n      \"outputs\": [\n        {\n          \"name\": \"MODEL\",\n          \"type\": \"MODEL\",\n          \"links\": [\n            89\n          ],\n          \"slot_index\": 0\n        },\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            154\n          ],\n          \"slot_index\": 1\n        },\n        {\n          \"name\": \"VAE\",\n          \"type\": \"VAE\",\n          \"links\": [],\n          \"slot_index\": 2\n        }\n      ],\n      \"title\": \"Load Checkpoint | id:checkpoint\",\n      \"properties\": {\n        \"Node name for S&R\": \"CheckpointLoaderSimple\"\n      },\n      \"widgets_values\": [\n        \"dreamshaper_8.safetensors\"\n      ]\n    },\n    {\n      \"id\": 98,\n      \"type\": \"CLIPSetLastLayer\",\n      \"pos\": [\n        -1115,\n        292\n      ],\n      \"size\": {\n        \"0\": 315,\n        \"1\": 58\n      },\n      \"flags\": {},\n      \"order\": 11,\n      \"mode\": 0,\n      \"inputs\": [\n        {\n          \"name\": \"clip\",\n          \"type\": \"CLIP\",\n          \"link\": 154\n        }\n      ],\n      \"outputs\": [\n        {\n          \"name\": \"CLIP\",\n          \"type\": \"CLIP\",\n          \"links\": [\n            155,\n            156\n          ],\n          \"shape\": 3,\n          \"slot_index\": 0\n        }\n      ],\n      \"title\": \"CLIP Set Last Layer | id:clip_skip\",\n      \"properties\": {\n        \"Node name for S&R\": \"CLIPSetLastLayer\"\n      },\n      \"widgets_values\": [\n        -1\n      ]\n    }\n  ],\n  \"links\": [\n    [\n      9,\n      8,\n      0,\n      9,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      15,\n      11,\n      0,\n      13,\n      0,\n      \"LATENT\"\n    ],\n    [\n      17,\n      13,\n      0,\n      12,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      36,\n      3,\n      0,\n      8,\n      0,\n      \"LATENT\"\n    ],\n    [\n      39,\n      5,\n      0,\n      3,\n      3,\n      \"LATENT\"\n    ],\n    [\n      78,\n      3,\n      0,\n      55,\n      0,\n      \"LATENT\"\n    ],\n    [\n      79,\n      55,\n      0,\n      11,\n      3,\n      \"LATENT\"\n    ],\n    [\n      81,\n      57,\n      0,\n      56,\n      0,\n      \"*\"\n    ],\n    [\n      82,\n      56,\n      0,\n      8,\n      1,\n      \"VAE\"\n    ],\n    [\n      83,\n      56,\n      0,\n      13,\n      1,\n      \"VAE\"\n    ],\n    [\n      87,\n      58,\n      1,\n      6,\n      0,\n      \"CLIP\"\n    ],\n    [\n      88,\n      58,\n      2,\n      6,\n      1,\n      \"STRING\"\n    ],\n    [\n      89,\n      16,\n      0,\n      59,\n      0,\n      \"*\"\n    ],\n    [\n      90,\n      59,\n      0,\n      60,\n      0,\n      \"MODEL\"\n    ],\n    [\n      93,\n      58,\n      0,\n      3,\n      0,\n      \"MODEL\"\n    ],\n    [\n      94,\n      60,\n      0,\n      58,\n      0,\n      \"MODEL\"\n    ],\n    [\n      97,\n      58,\n      0,\n      11,\n      0,\n      \"MODEL\"\n    ],\n    [\n      98,\n      60,\n      2,\n      7,\n      1,\n      \"STRING\"\n    ],\n    [\n      105,\n      63,\n      0,\n      3,\n      2,\n      \"CONDITIONING\"\n    ],\n    [\n      106,\n      62,\n      0,\n      3,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      107,\n      63,\n      0,\n      11,\n      2,\n      \"CONDITIONING\"\n    ],\n    [\n      108,\n      62,\n      0,\n      11,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      119,\n      60,\n      1,\n      7,\n      0,\n      \"CLIP\"\n    ],\n    [\n      131,\n      6,\n      0,\n      81,\n      0,\n      \"CONDITIONING\"\n    ],\n    [\n      135,\n      81,\n      3,\n      62,\n      0,\n      \"*\"\n    ],\n    [\n      136,\n      81,\n      4,\n      63,\n      0,\n      \"*\"\n    ],\n    [\n      137,\n      64,\n      0,\n      81,\n      2,\n      \"IMAGE\"\n    ],\n    [\n      140,\n      7,\n      0,\n      81,\n      1,\n      \"CONDITIONING\"\n    ],\n    [\n      146,\n      86,\n      0,\n      81,\n      3,\n      \"IMAGE\"\n    ],\n    [\n      147,\n      88,\n      0,\n      81,\n      4,\n      \"IMAGE\"\n    ],\n    [\n      148,\n      87,\n      0,\n      81,\n      5,\n      \"IMAGE\"\n    ],\n    [\n      149,\n      89,\n      0,\n      81,\n      7,\n      \"IMAGE\"\n    ],\n    [\n      150,\n      90,\n      0,\n      81,\n      6,\n      \"IMAGE\"\n    ],\n    [\n      151,\n      81,\n      0,\n      91,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      152,\n      81,\n      1,\n      92,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      153,\n      81,\n      2,\n      93,\n      0,\n      \"IMAGE\"\n    ],\n    [\n      154,\n      16,\n      1,\n      98,\n      0,\n      \"CLIP\"\n    ],\n    [\n      155,\n      98,\n      0,\n      58,\n      1,\n      \"CLIP\"\n    ],\n    [\n      156,\n      98,\n      0,\n      60,\n      1,\n      \"CLIP\"\n    ]\n  ],\n  \"groups\": [\n    {\n      \"title\": \"Txt2Img\",\n      \"bounding\": [\n        442,\n        -7,\n        1211,\n        708\n      ],\n      \"color\": \"#a1309b\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Save Intermediate Image\",\n      \"bounding\": [\n        1225,\n        500,\n        516,\n        196\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Hires Fix\",\n      \"bounding\": [\n        1210,\n        21,\n        710,\n        464\n      ],\n      \"color\": \"#b58b2a\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"Save Final Image\",\n      \"bounding\": [\n        1949,\n        31,\n        483,\n        199\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    },\n    {\n      \"title\": \"txt2img workflow\",\n      \"bounding\": [\n        646,\n        -1873,\n        1027,\n        134\n      ],\n      \"color\": \"#3f789e\",\n      \"font_size\": 24,\n      \"locked\": false\n    }\n  ],\n  \"config\": {},\n  \"extra\": {},\n  \"version\": 0.4\n}"
  },
  {
    "path": "typescripts/comfyui/util.ts",
    "content": "import { readdirSync, readFileSync } from 'fs'\nimport { requestPost } from '../util/ts/api'\n\nimport { storage } from 'uxp'\nimport { reaction, toJS } from 'mobx'\nimport { AStore } from '../main/astore'\n\nimport comfyapi from './comfyapi'\nimport { base64UrlToBase64 } from '../util/ts/general'\nimport { app } from 'photoshop'\nexport enum InputTypeEnum {\n    NumberField = 'NumberField',\n    TextField = 'TextField',\n    TextArea = 'TextArea',\n    Menu = 'Menu',\n    ImageBase64 = 'ImageBase64',\n}\nexport interface ValidInput {\n    [key: string]: any\n    value: string | number\n    label: string\n    list?: any[]\n    type: InputTypeEnum\n    id?: string\n}\nexport interface PhotoshopNode {\n    inputs: ValidInput[]\n    id: string\n}\n\nexport interface ComfyUIConfig {\n    [key: string]: any\n    checkpoints: string[]\n    samplers: string[]\n    schedulers: string[]\n}\n\nexport interface ComfyUINode {\n    inputs: any\n    class_type: string\n}\n// Assuming the json files are in a directory named 'native_workflows'\nconst dir = 'plugin:/typescripts/comfyui/native_workflows' // specify the directory containing the .json files\nlet workflows2: Record<string, any> = {}\nreaddirSync(dir).forEach((file) => {\n    if (file.endsWith('.json')) {\n        const fileContent = readFileSync(`${dir}/${file}`, 'utf8')\n        const fileNameWithoutExtension = file.slice(0, -5)\n        workflows2[fileNameWithoutExtension] = JSON.parse(fileContent)\n    }\n})\n\nexport const store = new AStore({\n    comfyui_valid_nodes: {} as any, // comfyui nodes like structure that contain all info necessary to create plugin ui elements\n    uuids: {} as any,\n\n    comfyui_output_images: [] as string[], //store the output images from generation\n    comfyui_output_thumbnail_images: [] as string[], // store thumbnail size images\n    comfyui_config: {} as ComfyUIConfig, // all config data like samplers, checkpoints ...etc\n    workflow_path: '', // the path of an image that contains prompt information\n    workflow_dir_path: '', // the path of the directory that contains all workflow files\n    // workflows_paths: [] as string[],\n    // workflows_names: [] as string[],\n    workflows: {} as any,\n    selected_workflow_name: '', // the selected workflow from the workflow menu\n    current_prompt: {} as any, // current prompt extracted from the workflow\n    thumbnail_image_size: 100,\n    load_image_nodes: {} as any, //our custom loadImageBase64 nodes, we need to substitute comfyui LoadImage nodes with before generating a prompt\n    // load_image_base64_strings: {} as any, //images the user added to the plugin comfy ui\n    object_info: undefined as any,\n    current_prompt2: {} as any,\n    current_prompt2_output: {} as any,\n    output_thumbnail_image_size: {} as Record<string, number>,\n\n    uploaded_images_base64_url: [] as string[],\n    current_uploaded_image: {} as Record<string, string>, //key: node_id, value: base64_url; only used in UI to show the selected images for LoadImage nodes\n    current_uploaded_video: {} as Record<string, string>,\n    uploaded_images_list: [] as string[], // store an array of all images in the comfy's input directory\n    uploaded_video_list: [] as string[], // store the name of .gif and .mp4 videos in comfy's input directory and subcategories\n    nodes_order: [] as string[], // nodes with smaller index will be rendered first,\n    can_edit_nodes: false as boolean,\n    nodes_label: {} as Record<string, string>,\n\n    workflows2: workflows2 as Record<string, any>,\n    user_custom_workflow: {} as Record<string, any>,\n    progress_value: 0,\n    is_random_seed: {} as Record<string, boolean>,\n    last_moved: undefined as string | undefined, // the last node that has been moved in the edit mode\n\n    base64_to_uploaded_images_names: {} as Record<string, any>,\n    can_generate: true as boolean,\n    infinite_loop: false as boolean,\n    output_node_fixed_height: {} as Record<string, boolean>,\n    lastCall: 0 as number,\n    // sync_from_canvas: {} as Record<string, boolean>,\n    loadImage_loading_method: {} as Record<string, ImageLoadingMethod>,\n})\n\ninterface ImageLoadingMethod {\n    method: 'Manual' | 'Sync From Whole Canvas' | 'Sync From a Layer'\n    data?: { layer_id?: number }\n}\ninterface Workflow {}\nexport function getNodes(workflow: Workflow) {\n    // Object.values(workflow).forEach((node) => {\n    //     console.log(node.class_type)\n    // })\n    return Object.entries(workflow)\n}\n\nexport enum ComfyInputType {\n    TextField = 'TextField',\n    TextArea = 'TextArea',\n    Menu = 'Menu',\n    Number = 'Number',\n    Slider = 'Slider',\n    BigNumber = 'BigNumber',\n    TextFieldNumber = 'TextFieldNumber',\n    Skip = 'Skip',\n    Seed = 'Seed',\n    CheckBox = 'CheckBox',\n}\nexport enum ComfyNodeType {\n    LoadImage = 'LoadImage',\n    LoadVideo = 'LoadVideo',\n    Normal = 'Normal',\n    Skip = 'Skip',\n}\n\ninterface ComfyOutputImage {\n    filename: string\n    subfolder: string\n    type: string\n}\n\nexport function getNodeType(node_name: any) {\n    let node_type: ComfyNodeType = ComfyNodeType.Normal\n    switch (node_name) {\n        case 'LoadImage':\n            node_type = ComfyNodeType.LoadImage\n            break\n        case 'LoadVideo':\n            node_type = ComfyNodeType.LoadVideo\n            break\n\n        default:\n            break\n    }\n    return node_type\n}\nexport function parseComfyInput(\n    name: string,\n    input_info: any,\n    prompt_value: any // the default value, set in the prompt api\n): {\n    type: ComfyInputType\n    config: any\n} {\n    let input_type: ComfyInputType = ComfyInputType.Skip\n    let input_config = input_info?.[1] || void 0\n    if (input_info === undefined) {\n        return { type: input_type, config: input_config }\n    }\n\n    try {\n        const value = input_info[0]\n\n        if (\n            (name === 'seed' || name === 'noise_seed') &&\n            !Array.isArray(prompt_value)\n        ) {\n            input_type = ComfyInputType.Seed // similar to big number\n            input_config = input_info[1]\n        } else if (typeof value === 'string') {\n            if (value === 'FLOAT' && !Array.isArray(prompt_value)) {\n                if (Number.isSafeInteger(input_config?.max)) {\n                    input_type = ComfyInputType.Slider\n                    input_config = input_info[1]\n                } else {\n                    input_type = ComfyInputType.TextFieldNumber\n                    input_config = input_info[1]\n                }\n            } else if (value === 'INT' && !Array.isArray(prompt_value)) {\n                if (input_info[1].max > Number.MAX_SAFE_INTEGER) {\n                    input_type = ComfyInputType.BigNumber\n                    input_config = input_info[1]\n                } else {\n                    input_type = ComfyInputType.TextFieldNumber\n                    input_config = input_info[1]\n                }\n            } else if (value === 'STRING' && !Array.isArray(prompt_value)) {\n                if (input_info[1]?.multiline) {\n                    input_type = ComfyInputType.TextArea\n                    input_config = input_info[1]\n                } else {\n                    input_type = ComfyInputType.TextField\n                    input_config = input_info[1]\n                }\n            } else if (value === 'BOOLEAN' && !Array.isArray(prompt_value)) {\n                input_type = ComfyInputType.CheckBox\n                input_config = input_info[1]\n            }\n        } else if (Array.isArray(value)) {\n            input_type = ComfyInputType.Menu\n            input_config = value\n        }\n    } catch (e) {\n        console.error(\n            `name:${name},\n    input_info:${input_info},\n    prompt_value:${prompt_value}`,\n            e\n        )\n    }\n    return { type: input_type, config: input_config }\n}\n\nexport function makeHtmlInput() {}\n\nasync function getHistory(prompt_id: string) {\n    while (true) {\n        const res = await comfyapi.comfy_api.queue()\n        if (res.queue_pending.length || res.queue_running.length) {\n            await new Promise((resolve) => setTimeout(resolve, 500))\n        } else {\n            break\n        }\n        await new Promise((resolve) => setTimeout(resolve, 500))\n    }\n    const history = await comfyapi.comfy_api.getHistory(prompt_id)\n    return history\n}\nexport async function postPromptAndGetBase64JsonResult(\n    prompt: Record<string, any>,\n    separated_output_nodes: string[] = []\n): Promise<{\n    outputs: Record<string, any> | undefined\n    separated_outputs: Record<string, any> | undefined\n}> {\n    try {\n        const res = await comfyapi.comfy_api.prompt(prompt)\n        if (!res) {\n            throw new Error(\n                `Unable to establish a connection to ComfyUI at the provided address: ${comfyapi.comfy_api.comfy_url}. Please ensure that ComfyUI is online and the URL is correct.`\n            )\n        }\n        if (res.error) {\n            const readable_error = comfyapi.comfy_api.getReadableError(res)\n            throw new Error(readable_error)\n        }\n        const prompt_id = res.prompt_id\n        const history = await getHistory(prompt_id)\n        const promptInfo = history[prompt_id]\n        if (Object.keys(promptInfo.outputs).length === 0) {\n            throw new Error(\n                `No images were generated. Please check the ComfyUI console for potential errors.`\n            )\n        }\n\n        const { outputs, separated_outputs } =\n            await mapComfyOutputToStoreOutput(\n                promptInfo.outputs,\n                separated_output_nodes\n            )\n        //         // [4][0] for output id.\n        //         const fileName = promptInfo.outputs[promptInfo.prompt[4][0]].images[0].filename\n        //         const resultB64 = await ComfyApi.view(this, fileName);\n        //         resultImages.push(resultB64)\n        //         if (option.imageFinishCallback) {\n        //             try { option.imageFinishCallback(resultB64, index) } catch (e) { }\n        //         }\n        // }\n        return { outputs, separated_outputs }\n    } catch (e) {\n        console.error(e)\n        app.showAlert(`${e}`)\n        throw e\n    }\n}\nexport const getFileFormat = (fileName: string): string =>\n    fileName.includes('.') ? fileName.split('.').pop()! : ''\n\nexport async function base64UrlFromComfy({\n    filename,\n    type,\n    subfolder,\n}: ComfyOutputImage) {\n    const base64 = await comfyapi.comfy_api.view(filename, type, subfolder)\n    return base64Url(base64, getFileFormat(filename))\n}\nexport function base64UrlFromFileName(base64: string, filename: string) {\n    return base64Url(base64, getFileFormat(filename))\n}\nexport function base64Url(base64: string, format: string = 'png') {\n    return `data:image/${format};base64,${base64}`\n}\nexport function generatePrompt(prompt: Record<string, any>) {\n    prompt\n}\nexport function updateOutput(output: any, output_store_obj: any) {\n    // store.data.current_prompt2_output[26] = [image, image]\n    output_store_obj = output\n}\n\nexport async function mapComfyOutputToStoreOutput(\n    comfy_output: Record<string, any>,\n    separated_output_nodes: string[] = []\n) {\n    const outputs: Record<string, any> = {}\n    const separated_outputs: Record<string, any> = {}\n\n    for (let key in comfy_output) {\n        let base64_url_list = await Promise.all(\n            (Object.values(comfy_output[key]).flat() as ComfyOutputImage[]).map(\n                async (output: ComfyOutputImage) => {\n                    try {\n                        if (['png'].includes(extractFormat(output.filename))) {\n                            return await base64UrlFromComfy(output)\n                        } else if (\n                            ['gif'].includes(extractFormat(output.filename))\n                        ) {\n                            const url = `${comfyapi.comfy_api.comfy_url}/view?subfolder=${output.subfolder}&type=${output.type}&filename=${output.filename}`\n                            return url\n                        }\n                    } catch (e) {\n                        console.error(output, e)\n                        return ''\n                    }\n                }\n            )\n        )\n        base64_url_list = base64_url_list.filter((item) => item !== '') // Filter out empty strings\n\n        if (separated_output_nodes.includes(key)) {\n            separated_outputs[key] = [\n                ...(separated_outputs[key] || []),\n                ...base64_url_list,\n            ]\n        } else {\n            outputs[key] = [...(outputs[key] || []), ...base64_url_list]\n        }\n    }\n\n    return { outputs, separated_outputs }\n}\n\ninterface LooseObject {\n    [key: string]: any\n}\n\nfunction isSameStructure(obj1: LooseObject, obj2: LooseObject): boolean {\n    // Get keys\n    const keys1 = Object.keys(obj1)\n    const keys2 = Object.keys(obj2)\n\n    // Check if both objects have the same number of keys\n    if (keys1.length !== keys2.length) {\n        return false\n    }\n\n    // Check if all keys in obj1 exist in obj2 and have the same structure\n    for (let i = 0; i < keys1.length; i++) {\n        const key = keys1[i]\n\n        // Check if the key exists in obj2\n        if (!obj2.hasOwnProperty(key)) {\n            return false\n        }\n\n        // If the value of this key is an object, check their structure recursively\n        if (\n            typeof obj1[key] === 'object' &&\n            obj1[key] !== null &&\n            typeof obj2[key] === 'object' &&\n            obj2[key] !== null\n        ) {\n            if (!isSameStructure(obj1[key], obj2[key])) {\n                return false\n            }\n        }\n    }\n\n    // If all checks passed, the structures are the same\n    return true\n}\n\nfunction extractFormat(input: string) {\n    let format: string = ''\n    if (input.includes('data:')) {\n        // Case for dataURL\n        format = input.split(':')[1].split(';')[0].split('/')[1]\n    } else if (input.includes('.')) {\n        // Case for file name with extension\n        format = input.split('.').pop() || ''\n    } else {\n        throw `input doesn't have an extension. input:${input}`\n    }\n    return format\n}\n\nasync function uploadImagePost(\n    buffer: any,\n    file_name: string,\n    type: string = 'input',\n    subfolder: string = 'Auto-Photoshop-SD'\n) {\n    try {\n        const full_url = comfyapi.comfy_api.comfy_url + '/upload/image'\n        var formData = new FormData()\n\n        formData.append('image', buffer, file_name)\n        formData.append('type', type)\n        formData.append('subfolder', subfolder)\n        var requestOptions = {\n            method: 'POST',\n            // header: myHeaders,\n            body: formData,\n        }\n        //@ts-ignore\n        const res = await fetch(full_url, requestOptions)\n\n        console.log(res.status, full_url)\n\n        const contentType = res.headers.get('Content-Type')\n\n        if (contentType?.indexOf('json') != -1) {\n            return res.json()\n        } else {\n            if (res.status == 200) {\n                return res.arrayBuffer()\n            } else {\n                return res.text()\n            }\n        }\n    } catch (e) {\n        console.error(e)\n    }\n}\nasync function uploadImage(\n    b_from_disk = false,\n    imgBase64: string,\n    type = 'input'\n) {\n    try {\n        let content, name\n        if (b_from_disk) {\n            const res = await readFile()\n            content = res.content\n            name = res.name\n        } else {\n            //from canvas\n            //@ts-ignore\n            const buffer = _base64ToArrayBuffer(imgBase64)\n            content = buffer\n            name = 'buffer.png'\n        }\n\n        // console.log('content: ', content)\n        // console.log('name: ', name)\n\n        const uploaded_image = await uploadImagePost(\n            content,\n            name,\n            type,\n            'Auto-Photoshop-SD'\n        )\n        return uploaded_image\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nasync function readFile() {\n    const entry = await storage.localFileSystem.getFileForOpening() // Prompts the user to select a file\n    // const contents = await entry.read('binary') // Reads the file as a string\n    const contents = await entry.read({\n        format: storage.formats.binary,\n    })\n    return { content: contents, name: entry.name }\n}\n\nfunction getRandomBigIntApprox(min: bigint, max: bigint): bigint {\n    min = BigInt(min)\n    max = BigInt(max)\n    const range = Number(max - min)\n    const rand = Math.floor(Math.random() * range)\n    return BigInt(rand) + min\n}\nfunction runRandomSeedScript() {\n    Object.entries(toJS(store.data.is_random_seed)).forEach(\n        ([node_id, is_random]) => {\n            if (is_random) {\n                const random_seed: bigint = getRandomBigIntApprox(\n                    0n,\n                    18446744073709552000n\n                )\n                Object.keys(store.data.current_prompt2[node_id].inputs).forEach(\n                    (name: string) => {\n                        if (['seed', 'noise_seed'].includes(name)) {\n                            store.data.current_prompt2[node_id].inputs[name] =\n                                random_seed.toString()\n                            // Usage\n                        }\n                    }\n                )\n            }\n        }\n    )\n}\nasync function maskExpansion(\n    base64_mask: string,\n    expansion: number,\n    blur: number\n) {\n    const prompt = {\n        '1': {\n            inputs: {\n                mask: base64_mask,\n                expansion: expansion,\n                blur: blur,\n            },\n            class_type: 'MaskExpansion',\n        },\n        '6': {\n            inputs: {\n                images: ['1', 0],\n            },\n            class_type: 'PreviewImage',\n        },\n    }\n    try {\n        var { outputs, separated_outputs } =\n            await postPromptAndGetBase64JsonResult(prompt)\n        if (outputs) {\n            const expanded_mask = outputs['6'][0]\n            return base64UrlToBase64(expanded_mask)\n        }\n        // html_manip.setInitImageMaskSrc(expanded_mask)\n    } catch (e) {\n        console.error(e)\n        outputs = undefined\n        separated_outputs = undefined\n    }\n    return base64_mask\n}\nexport default {\n    uploadImage,\n    uploadImagePost,\n    getNodes,\n    parseComfyInput,\n    getNodeType,\n    base64Url,\n    getFileFormat,\n    base64UrlFromComfy,\n    generatePrompt,\n    updateOutput,\n    getHistory,\n    mapComfyOutputToStoreOutput,\n    postPromptAndGetBase64JsonResult,\n    isSameStructure,\n    extractFormat,\n    getRandomBigIntApprox,\n    runRandomSeedScript,\n    maskExpansion,\n    workflows2,\n    ComfyInputType,\n    ComfyNodeType,\n    store,\n}\n"
  },
  {
    "path": "typescripts/controlnet/ControlNetTab.tsx",
    "content": "import { observer } from 'mobx-react'\nimport React from 'react'\nimport ControlNetUnit from './ControlNetUnit'\n\nimport ControlNetStore from './store'\nimport { DefaultControlNetUnitData } from './store'\nimport { Enum, controlnet_preset, note, selection } from '../util/oldSystem'\nimport { SpMenu, SpMenuComponent } from '../util/elements'\nimport Locale from '../locale/locale'\nimport { Collapsible } from '../util/collapsible'\nimport { PresetTypeEnum } from '../util/ts/enum'\nimport {\n    store as preset_store,\n    getAllCustomPresetsSettings,\n    getCustomPresetsNames,\n} from '../preset/shared_ui_preset'\n\nlet g_controlnet_presets: any\ndeclare const g_generation_session: any\n\n@observer\nclass ControlNetTab extends React.Component<{\n    appState: typeof ControlNetStore\n}> {\n    state = {\n        maxControlNet: 0,\n        presetMenuChildren: [],\n    }\n\n    // private presetMenuChildren: JSX.Element[] = []\n\n    // onPresetMenuChange(evt: any) {\n    //     // const preset_index = evt.target.selectedIndex\n    //     // const preset_name = evt.target.options[preset_index].textContent\n    //     ControlNetStore.controlNetUnitData.forEach((dataitem, index) => {\n    //         const presetData = g_controlnet_presets[preset_name][index] || {}\n\n    //         dataitem.enabled =\n    //             presetData.enabled || DefaultControlNetUnitData.enabled\n    //         dataitem.input_image =\n    //             presetData.input_image || DefaultControlNetUnitData.input_image\n    //         dataitem.mask = presetData.mask || DefaultControlNetUnitData.mask\n\n    //         dataitem.module =\n    //             presetData.module || DefaultControlNetUnitData.module\n    //         dataitem.model = presetData.model || DefaultControlNetUnitData.model\n    //         dataitem.weight =\n    //             presetData.weight || DefaultControlNetUnitData.weight\n    //         dataitem.resize_mode =\n    //             presetData.resize_mode || DefaultControlNetUnitData.resize_mode\n    //         dataitem.lowvram =\n    //             presetData.lowvram || DefaultControlNetUnitData.lowvram\n    //         dataitem.processor_res =\n    //             presetData.processor_res ||\n    //             DefaultControlNetUnitData.processor_res\n    //         dataitem.threshold_a =\n    //             presetData.threshold_a || DefaultControlNetUnitData.threshold_a\n    //         dataitem.threshold_b =\n    //             presetData.threshold_b || DefaultControlNetUnitData.threshold_b\n    //         dataitem.guidance_start =\n    //             presetData.guidance_start ||\n    //             DefaultControlNetUnitData.guidance_start\n    //         dataitem.guidance_end =\n    //             presetData.guidance_end ||\n    //             DefaultControlNetUnitData.guidance_end\n    //         dataitem.guessmode =\n    //             presetData.guessmode || DefaultControlNetUnitData.guessmode\n\n    //         dataitem.control_mode =\n    //             presetData.control_mode ||\n    //             DefaultControlNetUnitData.control_mode\n    //         dataitem.pixel_perfect =\n    //             presetData.pixel_perfect ||\n    //             DefaultControlNetUnitData.pixel_perfect\n    //     })\n    // }\n    // function to update presetMenuChildren\n    updatePresetMenuChildren(newChildren: any) {\n        this.setState({ presetMenuChildren: newChildren })\n    }\n    async updatePresetMenuEvent() {\n        const custom_presets = await getAllCustomPresetsSettings()\n        g_controlnet_presets = {\n            'Select CtrlNet Preset': {},\n            ...controlnet_preset.ControlNetNativePresets,\n            ...custom_presets,\n        }\n\n        const presets_names = Object.keys(g_controlnet_presets)\n\n        const presetMenuChildren = presets_names.map((preset_name) => {\n            if (preset_name == 'Select CtrlNet Preset')\n                return (\n                    <sp-menu-item\n                        key={preset_name}\n                        className=\"mControlNetPresetMenuItem\"\n                        selected\n                    >\n                        {preset_name}\n                    </sp-menu-item>\n                )\n            else\n                return (\n                    <sp-menu-item\n                        key={preset_name}\n                        className=\"mControlNetPresetMenuItem\"\n                    >\n                        {preset_name}\n                    </sp-menu-item>\n                )\n        })\n        this.updatePresetMenuChildren(presetMenuChildren)\n    }\n\n    async onSetAllControlImage() {\n        const selectionInfo = await selection.Selection.getSelectionInfoExe()\n        if (selectionInfo) {\n            const base64_image =\n                await g_generation_session.setControlNetImageHelper()\n\n            ControlNetStore.controlNetUnitData.forEach(async (data) => {\n                data.input_image = base64_image\n                data.selection_info = selectionInfo\n            })\n        } else {\n            await note.Notification.inactiveSelectionArea()\n        }\n    }\n\n    componentDidMount(): void {\n        this.updatePresetMenuEvent()\n    }\n\n    unitBackgroundColor(is_enabled: boolean, is_tab_enabled: boolean) {\n        let color\n        if (is_enabled && is_tab_enabled) {\n            color = '#ff595e'\n        } else if (is_enabled) {\n            color = '#2c4639'\n        } else {\n            color = void 0\n        }\n\n        return color\n    }\n\n    render() {\n        return (\n            <div>\n                {/* <SpMenu\n                    title=\"ControlNet Presets\"\n                    items={getCustomPresetsNames({\n                        ...preset_store.data.controlnet_native_presets,\n                        ...preset_store.data.controlnet_presets,\n                    })}\n                    label_item=\"Select a Preset\"\n                    selected_index={getCustomPresetsNames({\n                        ...preset_store.data.controlnet_native_presets,\n                        ...preset_store.data.controlnet_presets,\n                    }).indexOf(preset_store.data.current_controlnet_preset)}\n                    onChange={(id: any, value: any) => {\n                        console.log('value:', value)\n\n                        preset_store.data.current_controlnet_preset = value.item\n                        // this.onPresetMenuChange()\n                    }}\n                ></SpMenu> */}\n\n                <div></div>\n                {this.props.appState.maxControlNet == 0 && (\n                    <sp-label\n                        id=\"controlnetMissingError\"\n                        style={{ color: '#ff595e', whiteSpace: 'normal' }}\n                    >\n                        {Locale(\n                            'The Controlnet Extension is missing from Automatic1111.\\nPlease install it to use it through the plugin.'\n                        )}\n                    </sp-label>\n                )}\n                <div\n                    id=\"control_net_image_container\"\n                    className=\"imgContainer controlNetImaageContainer\"\n                >\n                    <div className=\"imgButton\">\n                        <button\n                            className=\"column-item btnSquare\"\n                            id=\"bSetAllControlImage\"\n                            onClick={this.onSetAllControlImage.bind(this)}\n                        >\n                            {Locale('Set All CtrlNet Images')}\n                        </button>\n                    </div>\n                    {/* <sp-checkbox id=\"chDisableControlNetTab\"> */}\n                    <sp-checkbox\n                        checked={\n                            this.props.appState.disableControlNetTab\n                                ? true\n                                : void 0\n                        }\n                        onClick={(\n                            event: React.ChangeEvent<HTMLInputElement>\n                        ) => {\n                            this.props.appState.disableControlNetTab =\n                                event.target.checked\n                        }}\n                    >\n                        {Locale('Disable ControlNet Tab')}\n                    </sp-checkbox>\n                </div>\n                <div>\n                    {Array(this.props.appState.maxControlNet)\n                        .fill(0)\n                        .map((v, index) => {\n                            const storeData =\n                                this.props.appState.controlNetUnitData[index]\n\n                            let controlNetLabel = `${Locale(\n                                'ControlNet Unit'\n                            )} ${index}: ${\n                                storeData.module && storeData.module !== 'none'\n                                    ? `${storeData.module}`\n                                    : ''\n                            }`\n\n                            return (\n                                <div\n                                    key={index}\n                                    style={{\n                                        border: '2px solid #6d6c6c',\n                                        padding: '3px',\n                                    }}\n                                >\n                                    <Collapsible\n                                        defaultIsOpen={false}\n                                        label={controlNetLabel}\n                                        labelStyle={{ fontSize: '12px' }}\n                                        containerStyle={{\n                                            alignItems: 'center',\n                                            backgroundColor:\n                                                this.unitBackgroundColor(\n                                                    storeData.enabled,\n                                                    this.props.appState\n                                                        .disableControlNetTab\n                                                ),\n                                        }}\n                                        checkboxCallback={(checked) => {\n                                            storeData.enabled = checked\n                                        }}\n                                        checked={storeData.enabled}\n                                    >\n                                        <div style={{ paddingTop: '10px' }}>\n                                            <ControlNetUnit\n                                                appState={this.props.appState}\n                                                // key={index}\n                                                index={index}\n                                            />\n                                        </div>\n                                    </Collapsible>\n                                </div>\n                            )\n                        })}\n                </div>\n            </div>\n        )\n    }\n}\n\nexport default ControlNetTab\n"
  },
  {
    "path": "typescripts/controlnet/ControlNetUnit.tsx",
    "content": "import { observer } from 'mobx-react'\nimport React from 'react'\nimport {\n    MoveToCanvasSvg,\n    ActionButtonSVG,\n    SpCheckBox,\n    SpMenu,\n    SpSlider,\n    Thumbnail,\n    PenSvg,\n    PreviewSvg,\n    SpSliderWithLabel,\n    SliderType,\n    SearchableMenu,\n} from '../util/elements'\nimport ControlNetStore, { ControlnetMode, controlnetModes } from './store'\nimport { mapRange, versionCompare } from './util'\nimport {\n    note,\n    selection,\n    html_manip,\n    psapi,\n    api,\n    general,\n} from '../util/oldSystem'\nimport Locale from '../locale/locale'\nimport { requestControlNetFiltersKeywords } from './entry'\n\ndeclare const g_generation_session: any\ndeclare const io: any\ndeclare const app: any\ndeclare let g_sd_url: string\n\n@observer\nexport default class ControlNetUnit extends React.Component<\n    { index: number; appState: typeof ControlNetStore },\n    {}\n> {\n    onEnableChange(event: any) {\n        event.preventDefault()\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.enabled = !storeData.enabled\n    }\n    onLowVRamChange(event: any) {\n        event.preventDefault()\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.lowvram = !storeData.lowvram\n    }\n    onGuessModeChange(event: any) {\n        event.preventDefault()\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.guessmode = !storeData.guessmode\n    }\n    onPixelPerfectChange(event: any) {\n        event.preventDefault()\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        console.log('onPixelPerfectChange', storeData.pixel_perfect)\n        storeData.pixel_perfect = !storeData.pixel_perfect\n    }\n    onAutoImageChange(event: any) {\n        event.preventDefault()\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        console.log('onAutoImageChange', storeData.auto_image)\n        storeData.auto_image = !storeData.auto_image\n    }\n    onWeightMove(event: any) {\n        event.preventDefault()\n        if (event.target.tagName != 'SP-SLIDER') return\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.weight = +mapRange(\n            event.target.value,\n            0,\n            200,\n            0,\n            2,\n            0.01\n        ).toFixed(2)\n    }\n    onGuidanceStartMove(event: any) {\n        event.preventDefault()\n        if (event.target.tagName != 'SP-SLIDER') return\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.guidance_start = +mapRange(\n            event.target.value,\n            0,\n            10,\n            0,\n            1,\n            0.1\n        ).toFixed(1)\n    }\n    onGuidanceEndMove(event: any) {\n        event.preventDefault()\n        if (event.target.tagName != 'SP-SLIDER') return\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.guidance_end = +mapRange(\n            event.target.value,\n            0,\n            10,\n            0,\n            1,\n            0.1\n        ).toFixed(1)\n    }\n    async onFilterChange(\n        event: any,\n        { index, item }: { index: number; item: string }\n    ) {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.filter_keyword = item\n        if (storeData.filter_keyword.toLowerCase() === 'none') {\n            storeData.module_list = this.props.appState.supportedPreprocessors\n            storeData.model_list = ['None'].concat(\n                this.props.appState.supportedModels\n            )\n        } else {\n            const filters = await requestControlNetFiltersKeywords(\n                storeData.filter_keyword,\n                this.props.appState.supportedPreprocessors,\n                this.props.appState.supportedModels\n            )\n\n            storeData.module_list = filters.module_list\n            storeData.model_list = filters.model_list\n            storeData.model = filters.default_model\n            storeData.module = filters.default_option\n            storeData.model = filters.default_model\n        }\n    }\n    onPreprocsesorChange(item: string) {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.module = item\n    }\n    onModelChange(item: string) {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        storeData.model = item\n    }\n    onResolutionMove(event: any) {\n        event.preventDefault()\n        if (event.target.tagName != 'SP-SLIDER') return\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        let resolutionConfig =\n            this.props.appState.preprocessorDetail[storeData.module] || {}\n        let sliderConfig = resolutionConfig.sliders[0]\n        storeData.processor_res = +(\n            event.target.value * (sliderConfig.step || 1)\n        )\n    }\n    onThresholdAMove(event: any) {\n        event.preventDefault()\n        if (event.target.tagName != 'SP-SLIDER') return\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        let resolutionConfig =\n            this.props.appState.preprocessorDetail[storeData.module] || {}\n        let sliderConfig = resolutionConfig.sliders[1]\n        storeData.threshold_a = +(event.target.value * (sliderConfig.step || 1))\n    }\n    onThresholdBMove(event: any) {\n        event.preventDefault()\n        if (event.target.tagName != 'SP-SLIDER') return\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        let resolutionConfig =\n            this.props.appState.preprocessorDetail[storeData.module] || {}\n        let sliderConfig = resolutionConfig.sliders[2]\n        storeData.threshold_b = +(event.target.value * (sliderConfig.step || 1))\n    }\n    async onSetImageButtonClick() {\n        const selectionInfo = await selection.Selection.getSelectionInfoExe()\n        if (selectionInfo) {\n            const base64_image =\n                await g_generation_session.setControlNetImageHelper()\n\n            const storeData =\n                this.props.appState.controlNetUnitData[this.props.index]\n            storeData.input_image = base64_image\n            storeData.selection_info = selectionInfo\n        } else {\n            await note.Notification.inactiveSelectionArea()\n        }\n    }\n    async onMaskButtonClick() {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        if (storeData.selection_info && storeData.mask) {\n            const selection_info = storeData.selection_info\n            const layer = await io.IO.base64ToLayer(\n                storeData.mask,\n                'ControlNet Mask.png',\n                selection_info.left,\n                selection_info.top,\n                selection_info.width,\n                selection_info.height\n            )\n        } else {\n            // await note.Notification.inactiveSelectionArea()\n            app.showAlert('Mask Image is not available')\n        }\n    }\n\n    async requestControlNetDetectMap(\n        controlnet_init_image: string,\n        _module: string,\n        processor_res: number,\n        threshold_a: number,\n        threshold_b: number\n    ) {\n        try {\n            const payload = {\n                controlnet_module: _module,\n                controlnet_input_images: [controlnet_init_image],\n                controlnet_processor_res: processor_res,\n                controlnet_threshold_a: threshold_a,\n                controlnet_threshold_b: threshold_b,\n            }\n            const full_url = `${g_sd_url}/controlnet/detect`\n\n            const response_data = await api.requestPost(full_url, payload)\n\n            // update the mask preview with the new detectMap\n            if (response_data['images'].length === 0) {\n                app.showAlert(response_data['info'])\n            }\n            return response_data['images'][0]\n        } catch (e) {\n            console.warn('requestControlNetDetectMap(): ', _module, e)\n        }\n    }\n\n    async previewAnnotator() {\n        const index = this.props.index\n        try {\n            const storeData = this.props.appState.controlNetUnitData[index]\n\n            const controlnet_init_image = storeData.input_image\n\n            const _module = storeData.module || 'none'\n            const processor_res = storeData.processor_res\n            const threshold_a = storeData.threshold_a\n            const threshold_b = storeData.threshold_b\n\n            if (!controlnet_init_image) {\n                const error = 'ControlNet initial image is empty'\n                app.showAlert(error)\n                throw error\n            }\n            if (!_module || _module === 'none') {\n                const error = 'select a valid controlnet module (preprocessor)'\n                app.showAlert(error)\n                throw error\n            }\n\n            const detect_map = await this.requestControlNetDetectMap(\n                controlnet_init_image,\n                _module,\n                processor_res,\n                threshold_a,\n                threshold_b\n            )\n\n            const rgb_detect_map_url =\n                await io.convertBlackAndWhiteImageToRGBChannels3(detect_map)\n            const rgb_detect_map = general.base64UrlToBase64(rgb_detect_map_url)\n            // g_generation_session.controlNetMask[index] = rgb_detect_map\n            storeData.detect_map = rgb_detect_map\n        } catch (e) {\n            console.warn('PreviewAnnotator click(): index: ', index, e)\n        }\n    }\n    async setMask() {\n        try {\n            const selectionInfo = await psapi.getSelectionInfoExe()\n            if (selectionInfo) {\n                const mask_base64 = await io.getMaskFromCanvas()\n                this.props.appState.controlNetUnitData[this.props.index].mask =\n                    mask_base64\n            } else {\n                // await note.Notification.inactiveSelectionArea()\n                app.showAlert('No Selection is available')\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    async resetMask() {\n        this.props.appState.controlNetUnitData[this.props.index].mask = ''\n    }\n    async toCanvas() {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        if (storeData.selection_info && storeData.detect_map) {\n            const selection_info = storeData.selection_info\n\n            const layer = await io.IO.base64ToLayer(\n                storeData.detect_map,\n                'ControlNet Detection Map.png',\n                selection_info.left,\n                selection_info.top,\n                selection_info.width,\n                selection_info.height\n            )\n        } else {\n            // await note.Notification.inactiveSelectionArea()\n            app.showAlert('Detection Map is not available')\n        }\n    }\n    async toControlNetInitImage() {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n\n        storeData.input_image = storeData.detect_map\n    }\n    async previewAnnotatorFromCanvas() {\n        try {\n            const storeData =\n                this.props.appState.controlNetUnitData[this.props.index]\n            const _module = storeData.module || 'none'\n\n            const width = html_manip.getWidth()\n            const height = html_manip.getHeight()\n            const selectionInfo = await psapi.getSelectionInfoExe()\n            storeData.selection_info = selectionInfo\n            const base64 =\n                await io.IO.getSelectionFromCanvasAsBase64Interface_New(\n                    width,\n                    height,\n                    selectionInfo,\n                    true\n                )\n\n            if (!_module || _module === 'none') {\n                const error = 'select a valid controlnet module (preprocessor)'\n                app.showAlert(error)\n                throw error\n            }\n\n            const processor_res = storeData.processor_res\n            const threshold_a = storeData.threshold_a\n            const threshold_b = storeData.threshold_b\n\n            const detect_map = await this.requestControlNetDetectMap(\n                base64,\n                _module,\n                processor_res,\n                threshold_a,\n                threshold_b\n            )\n\n            const rgb_detect_map_url =\n                await io.convertBlackAndWhiteImageToRGBChannels3(detect_map)\n            g_generation_session.controlNetMask[this.props.index] = detect_map\n\n            storeData.detect_map = general.base64UrlToBase64(rgb_detect_map_url)\n        } catch (e) {\n            console.warn(\n                'PreviewAnnotator click(): index: ',\n                this.props.index,\n                e\n            )\n        }\n    }\n    render() {\n        const storeData =\n            this.props.appState.controlNetUnitData[this.props.index]\n        const pd =\n            this.props.appState.preprocessorDetail[storeData.module] || {}\n        const ppSlider = pd.sliders || []\n\n        return (\n            <div id={`controlnet_settings_${this.props.index}`}>\n                {/* <div className=\"flexContainer\">\n                    <SpCheckBox\n                        style={{ marginRight: '10px' }}\n                        onChange={this.onEnableChange.bind(this)}\n                        checked={storeData.enabled}\n                        id={`chEnableControlNet_${this.props.index}`}\n                        value={\n                            this.props.appState.controlNetUnitData[\n                                this.props.index\n                            ].enabled\n                        }\n                    >\n                        ControlNet Unit {this.props.index}{' '}\n                        {storeData.module && storeData.module !== 'none'\n                            ? `(${storeData.module})`\n                            : void 0}\n                    </SpCheckBox>\n                </div> */}\n                <div\n                    style={{\n                        display: 'block',\n                        // display: storeData.enabled ? 'block' : 'none'\n                    }}\n                >\n                    <div style={{ display: 'flex' }}>\n                        <div\n                            id={`control_net_image_container_${this.props.index}`}\n                            className=\"imgContainer controlNetImaageContainer\"\n                        >\n                            <div>\n                                <img\n                                    id={`control_net_image_${this.props.index}`}\n                                    className=\"column-item-image\"\n                                    src={\n                                        storeData.input_image\n                                            ? 'data:image/png;base64,' +\n                                              storeData.input_image\n                                            : 'https://source.unsplash.com/random'\n                                    }\n                                    width=\"300px\"\n                                    height=\"100px\"\n                                />\n                            </div>\n                            <div className=\"imgButton\">\n                                <button\n                                    className=\"column-item button-style btnSquare\"\n                                    id={`bSetControlImage_${this.props.index}`}\n                                    onClick={this.onSetImageButtonClick.bind(\n                                        this\n                                    )}\n                                    title=\"Set CtrlNet Img\"\n                                >\n                                    {Locale('Set CtrlImg')}\n                                </button>\n                            </div>\n                        </div>\n                        <div\n                            id={`control_net_mask_container_${this.props.index}`}\n                            className=\"imgContainer controlNetImaageContainer\"\n                        >\n                            <div>\n                                <Thumbnail>\n                                    <img\n                                        id={`control_net_mask_${this.props.index}`}\n                                        className=\"column-item-image\"\n                                        src={\n                                            storeData.detect_map\n                                                ? 'data:image/png;base64,' +\n                                                  storeData.detect_map\n                                                : 'https://source.unsplash.com/random'\n                                        }\n                                        width=\"300px\"\n                                        height=\"100px\"\n                                    />\n                                    <ActionButtonSVG\n                                        ComponentType={PenSvg}\n                                        onClick={this.toControlNetInitImage.bind(\n                                            this\n                                        )}\n                                        title={Locale(\n                                            'use as controlnet input image'\n                                        )}\n                                    ></ActionButtonSVG>\n                                    <ActionButtonSVG\n                                        ComponentType={MoveToCanvasSvg}\n                                        onClick={this.toCanvas.bind(this)}\n                                        title={Locale('Copy Image to Canvas')}\n                                    ></ActionButtonSVG>\n                                    <ActionButtonSVG\n                                        ComponentType={PreviewSvg}\n                                        onClick={this.previewAnnotatorFromCanvas.bind(\n                                            this\n                                        )}\n                                        title={Locale(\n                                            'Preview Annotation From the Selected Area on Canvas'\n                                        )}\n                                    ></ActionButtonSVG>\n                                </Thumbnail>\n                            </div>\n                            <div className=\"imgButton btnClass\">\n                                <button\n                                    className=\"column-item button-style btnSquare\"\n                                    id={`bControlMask_${this.props.index}`}\n                                    onClick={this.previewAnnotator.bind(this)}\n                                    title=\"Preview Annotator\"\n                                >\n                                    {Locale('Preview Annotator')}\n                                </button>\n                            </div>\n                        </div>\n\n                        {!this.props.appState.controlNetUnitData[\n                            this.props.index\n                        ].model\n                            .toLowerCase()\n                            .includes('inpaint') ? (\n                            void 0\n                        ) : (\n                            <div className=\"imgContainer controlNetImaageContainer\">\n                                <div>\n                                    <Thumbnail>\n                                        <img\n                                            className=\"column-item-image\"\n                                            src={\n                                                storeData.mask\n                                                    ? 'data:image/png;base64,' +\n                                                      storeData.mask\n                                                    : 'https://source.unsplash.com/random'\n                                            }\n                                            width=\"300px\"\n                                            height=\"100px\"\n                                        />\n\n                                        <ActionButtonSVG\n                                            ComponentType={PenSvg}\n                                            onClick={this.setMask.bind(this)}\n                                            title={Locale(\n                                                'set the mask for controlnet inpaint mode'\n                                            )}\n                                        ></ActionButtonSVG>\n                                        <ActionButtonSVG\n                                            ComponentType={PenSvg}\n                                            onClick={this.resetMask.bind(this)}\n                                            title={Locale('reset the mask')}\n                                        ></ActionButtonSVG>\n                                    </Thumbnail>\n                                </div>\n                                <div className=\"imgButton btnClass\">\n                                    <button\n                                        className=\"column-item button-style btnSquare\"\n                                        id={`bControlMask_${this.props.index}`}\n                                        onClick={this.setMask.bind(this)}\n                                        title=\"Preview Annotator\"\n                                    >\n                                        {Locale('Set Mask')}\n                                    </button>\n                                </div>\n                            </div>\n                        )}\n                    </div>\n\n                    <SpCheckBox\n                        style={{ marginRight: '10px' }}\n                        onChange={this.onLowVRamChange.bind(this)}\n                        checked={storeData.lowvram}\n                        id={`chlowVram_${this.props.index}`}\n                    >\n                        {Locale('Low VRAM')}\n                    </SpCheckBox>\n                    <SpCheckBox\n                        style={{\n                            display:\n                                this.props.appState.controlnetApiVersion > 1\n                                    ? 'none'\n                                    : void 0,\n                            marginRight: '10px',\n                        }}\n                        onChange={this.onGuessModeChange.bind(this)}\n                        checked={storeData.guessmode}\n                        id={`chGuessMode_${this.props.index}`}\n                    >\n                        {Locale('Guess Mode')}\n                    </SpCheckBox>\n                    <SpCheckBox\n                        style={{\n                            display:\n                                this.props.appState.controlnetApiVersion > 1\n                                    ? void 0\n                                    : 'none',\n                            marginRight: '10px',\n                        }}\n                        onChange={this.onPixelPerfectChange.bind(this)}\n                        checked={storeData.pixel_perfect}\n                        id={`chPixelPerfect_${this.props.index}`}\n                    >\n                        {Locale('Pixel Perfect')}\n                    </SpCheckBox>\n                    <SpCheckBox\n                        style={{\n                            marginRight: '10px',\n                        }}\n                        onChange={this.onAutoImageChange.bind(this)}\n                        checked={storeData.auto_image}\n                        // id={`chPixelPerfect_${this.props.index}`}\n                        title={Locale(\n                            'load the input image from canvas automatically'\n                        )}\n                    >\n                        {\n                            //@ts-ignore\n                            Locale('Auto Image')\n                        }\n                    </SpCheckBox>\n                    {this.props.appState.controlnetApiVersion > 1 && (\n                        <sp-radio-group\n                            style={{ display: 'flex' }}\n                            selected={\n                                this.props.appState.controlNetUnitData[\n                                    this.props.index\n                                ].control_mode\n                            }\n                            onClick={(event: any) => {\n                                this.props.appState.controlNetUnitData[\n                                    this.props.index\n                                ].control_mode = event.target.value\n                            }}\n                        >\n                            <sp-label slot=\"label\">\n                                {Locale('Control Mode')}\n                            </sp-label>\n                            {controlnetModes.map(\n                                (mode: ControlnetMode, index: number) => {\n                                    // console.log('mode:', mode, ' index:', index)\n                                    return (\n                                        <sp-radio\n                                            key={`mode-${index}`}\n                                            checked={\n                                                this.props.appState\n                                                    .controlNetUnitData[\n                                                    this.props.index\n                                                ].control_mode === mode\n                                                    ? true\n                                                    : void 0\n                                            }\n                                            value={`${mode}`}\n                                        >\n                                            {Locale(mode)}\n                                        </sp-radio>\n                                    )\n                                }\n                            )}\n                        </sp-radio-group>\n                    )}\n\n                    <div>\n                        <div>\n                            <SpSlider\n                                show-value=\"false\"\n                                min={0}\n                                max={200}\n                                value={storeData.weight * 100}\n                                onInput={this.onWeightMove.bind(this)}\n                                title=\"2 will keep the composition; 0 will allow composition to change\"\n                            >\n                                <sp-label slot=\"label\">\n                                    {Locale('Control Weight')}\n                                </sp-label>\n                                <sp-label slot=\"label\">\n                                    {storeData.weight}\n                                </sp-label>\n                            </SpSlider>\n                            <SpSlider\n                                show-value=\"false\"\n                                min=\"0\"\n                                max=\"10\"\n                                value={\n                                    +mapRange(\n                                        storeData.guidance_start,\n                                        0,\n                                        1,\n                                        0,\n                                        10,\n                                        1\n                                    ).toFixed(1)\n                                }\n                                onInput={this.onGuidanceStartMove.bind(this)}\n                            >\n                                <sp-label slot=\"label\">\n                                    {Locale('Guidance Start (T)')}\n                                </sp-label>\n                                <sp-label\n                                    slot=\"label\"\n                                    id={`lControlNetGuidanceStrengthStart_${this.props.index}`}\n                                >\n                                    {storeData.guidance_start}\n                                </sp-label>\n                            </SpSlider>\n                            <SpSlider\n                                show-value=\"false\"\n                                min=\"0\"\n                                max=\"10\"\n                                value={\n                                    +mapRange(\n                                        storeData.guidance_end,\n                                        0,\n                                        1,\n                                        0,\n                                        10,\n                                        1\n                                    ).toFixed(1)\n                                }\n                                onInput={this.onGuidanceEndMove.bind(this)}\n                            >\n                                <sp-label slot=\"label\">\n                                    {Locale('Guidance End (T)')}\n                                </sp-label>\n                                <sp-label\n                                    slot=\"label\"\n                                    id={`lControlNetGuidanceStrengthEnd_${this.props.index}`}\n                                >\n                                    {storeData.guidance_end}\n                                </sp-label>\n                            </SpSlider>\n                            {ppSlider &&\n                                ppSlider[0] &&\n                                !storeData.pixel_perfect && (\n                                    <SpSlider\n                                        show-value=\"false\"\n                                        min={\n                                            ppSlider[0].min /\n                                            (ppSlider[0].step || 1)\n                                        }\n                                        max={\n                                            ppSlider[0].max /\n                                            (ppSlider[0].step || 1)\n                                        }\n                                        value={\n                                            storeData.processor_res /\n                                            (ppSlider[0].step || 1)\n                                        }\n                                        onInput={this.onResolutionMove.bind(\n                                            this\n                                        )}\n                                    >\n                                        <sp-label slot=\"label\">\n                                            {ppSlider[0].name}:\n                                        </sp-label>\n                                        <sp-label slot=\"label\">\n                                            {storeData.processor_res.toFixed(2)}\n                                        </sp-label>\n                                    </SpSlider>\n                                )}\n                            {ppSlider && ppSlider[1] && (\n                                <SpSlider\n                                    show-value=\"false\"\n                                    min={\n                                        ppSlider[1].min /\n                                        (ppSlider[1].step || 1)\n                                    }\n                                    max={\n                                        ppSlider[1].max /\n                                        (ppSlider[1].step || 1)\n                                    }\n                                    value={\n                                        storeData.threshold_a /\n                                        (ppSlider[1].step || 1)\n                                    }\n                                    onInput={this.onThresholdAMove.bind(this)}\n                                >\n                                    <sp-label slot=\"label\">\n                                        {ppSlider[1].name}:\n                                    </sp-label>\n                                    <sp-label slot=\"label\">\n                                        {storeData.threshold_a.toFixed(2)}\n                                    </sp-label>\n                                </SpSlider>\n                            )}\n                            {ppSlider && ppSlider[2] && (\n                                <SpSlider\n                                    show-value=\"false\"\n                                    min={\n                                        ppSlider[2].min /\n                                        (ppSlider[2].step || 1)\n                                    }\n                                    max={\n                                        ppSlider[2].max /\n                                        (ppSlider[2].step || 1)\n                                    }\n                                    value={\n                                        storeData.threshold_b /\n                                        (ppSlider[2].step || 1)\n                                    }\n                                    onInput={this.onThresholdBMove.bind(this)}\n                                >\n                                    <sp-label slot=\"label\">\n                                        {ppSlider[2].name}:\n                                    </sp-label>\n                                    <sp-label slot=\"label\">\n                                        {storeData.threshold_b.toFixed(2)}\n                                    </sp-label>\n                                </SpSlider>\n                            )}\n                        </div>\n                    </div>\n                    <div style={{ width: '50%', display: 'flex' }}>\n                        <SpMenu\n                            onChange={this.onFilterChange.bind(this)}\n                            items={this.props.appState.filterKeywords}\n                            label_item={Locale('Select Filter')}\n                            selected_index={this.props.appState.filterKeywords.indexOf(\n                                storeData.filter_keyword || 'All'\n                            )}\n                            // style={{ width: '50%', display: 'flex' }}\n                        />\n                    </div>\n                    <div\n                        id={`menu-bar-control_net_${this.props.index}`}\n                        style={{ display: 'flex' }}\n                    >\n                        <div style={{ width: '50%', display: 'flex' }}>\n                            {/* <SpMenu\n                                onChange={this.onPreprocsesorChange.bind(this)}\n                                id={`mModulesMenuControlNet_${this.props.index}`}\n                                items={storeData.module_list || ['none']}\n                                label_item={Locale('Select Module')}\n                                selected_index={storeData.module_list?.indexOf(\n                                    storeData.module\n                                )}\n                                style={{ width: '100%' }}\n                            /> */}\n                            <SearchableMenu\n                                allItems={storeData.module_list || ['none']}\n                                placeholder={Locale('Select Module')}\n                                selected_item={storeData.module}\n                                onSelectItemFailure={() => {\n                                    const default_value =\n                                        // storeData.module_list[0] || 'None'\n                                        'None'\n\n                                    storeData.module = default_value\n                                    return default_value\n                                }}\n                                onChange={(item: any) => {\n                                    this.onPreprocsesorChange(item)\n                                }}\n                            />\n                        </div>\n                        {!pd.model_free && (\n                            <div style={{ width: '50%', display: 'flex' }}>\n                                {/* <SpMenu\n                                    onChange={this.onModelChange.bind(this)}\n                                    id={`mModelsMenuControlNet_${this.props.index}`}\n                                    items={storeData.model_list || []}\n                                    label_item={Locale('Select Module')}\n                                    selected_index={storeData.model_list?.indexOf(\n                                        storeData.model\n                                    )}\n                                    style={{ width: '100%' }}\n                                /> */}\n                                <SearchableMenu\n                                    allItems={storeData.model_list || ['none']}\n                                    placeholder={Locale('Selec Model')}\n                                    selected_item={storeData.model}\n                                    onSelectItemFailure={() => {\n                                        const default_value =\n                                            // storeData.model_list[0] || 'None'\n                                            'None'\n                                        storeData.model = default_value\n                                        return default_value\n                                    }}\n                                    onChange={(item: any) => {\n                                        this.onModelChange(item)\n                                    }}\n                                />\n                            </div>\n                        )}\n                    </div>\n                </div>\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "typescripts/controlnet/entry.ts",
    "content": "import { toJS } from 'mobx'\nimport { setControlImageSrc } from '../../utility/html_manip'\n// import { session_ts } from '../entry'\n// import * as session_ts from '../session/session'\nimport { store as session_store } from '../session/session_store'\nimport { Enum, api, io, python_replacement } from '../util/oldSystem'\nimport { GenerationModeEnum } from '../util/ts/enum'\nimport store, {\n    DefaultControlNetUnitData,\n    DefaultPresetControlNetUnitData,\n    controlNetUnitData,\n} from './store'\n\nconst { getExtensionUrl } = python_replacement\ndeclare const g_sd_config_obj: any\ndeclare let g_sd_url: string\n\nfunction convertComfyModuleDetailsToPluginModuleDetails(\n    comfy_module_details: Record<string, any>\n) {\n    let outputJson: Record<string, any> = {}\n    for (let preprocessorName in comfy_module_details) {\n        let preprocessorConfig = comfy_module_details[preprocessorName]\n        let sliders = []\n        if (preprocessorConfig.resolution) {\n            sliders.push({\n                name: `${preprocessorName} Resolution`,\n                value: preprocessorConfig.resolution,\n                min: 64,\n                max: 2048,\n            })\n        }\n        if (preprocessorConfig.param_config) {\n            for (let paramName in preprocessorConfig.param_config) {\n                let paramConfig = preprocessorConfig.param_config[paramName]\n                sliders.push({\n                    name: `${paramName}`,\n                    value: preprocessorConfig[paramName],\n                    min: paramConfig.min,\n                    max: paramConfig.max,\n                })\n            }\n        }\n        outputJson[preprocessorName] = {\n            model_free: false,\n            sliders: sliders,\n        }\n    }\n    return outputJson\n}\n\nasync function requestControlNetPreprocessors() {\n    const control_net_json = await api.requestGet(\n        `${g_sd_url}/controlnet/module_list?alias_names=true`\n    )\n\n    return control_net_json\n}\nasync function requestControlNetModelList(): Promise<any> {\n    const control_net_json = await api.requestGet(\n        `${g_sd_url}/controlnet/model_list`\n    )\n\n    const model_list = control_net_json?.model_list\n    return model_list\n}\nasync function requestControlNetApiVersion() {\n    const json = await api.requestGet(`${g_sd_url}/controlnet/version`)\n\n    const version = json?.version\n\n    return version\n}\nasync function requestControlNetMaxUnits() {\n    const json = await api.requestGet(`${g_sd_url}/controlnet/settings`)\n\n    const control_net_max_models_num =\n        (json?.control_net_unit_count || json?.control_net_max_models_num) ?? 0\n\n    return control_net_max_models_num\n}\n\nasync function requestControlNetFiltersKeywords(\n    keyword = 'All',\n    module_list: string[],\n    model_list: string[]\n) {\n    try {\n        const extension_url = getExtensionUrl()\n        // const full_url = `${extension_url}/controlnet/filter?keyword=${keyword}`\n\n        const full_url = `${extension_url}/controlnet/filter`\n\n        const payload = {\n            keyword: keyword,\n            preprocessor_list: module_list,\n            model_list: model_list,\n        }\n        //const full_url = `${g_sd_url}/controlnet/filter?keyword=${keyword}`\n        const control_net_json = await api.requestPost(full_url, payload)\n\n        return control_net_json\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function initializeControlNetTab(controlnet_max_models: number) {\n    store.maxControlNet = controlnet_max_models || store.maxControlNet\n    store.controlnetApiVersion = await requestControlNetApiVersion()\n\n    try {\n        const models = await requestControlNetModelList()\n        store.supportedModels = models || []\n    } catch (e) {\n        console.warn(e)\n    }\n    try {\n        const pps = await requestControlNetPreprocessors()\n        store.supportedPreprocessors = pps ? pps.module_list : []\n        store.preprocessorDetail = pps ? pps.module_detail : {}\n    } catch (e) {\n        console.warn(e)\n    }\n    try {\n        //retrieve all keywords to popular the dropdown menu\n\n        const filters = await requestControlNetFiltersKeywords(\n            'All',\n            store.supportedPreprocessors,\n            store.supportedModels\n        )\n\n        store.filterKeywords = filters\n            ? ['none'].concat(filters.keywords)\n            : ['none']\n        if (filters) {\n            store.controlNetUnitData.forEach((unitData) => {\n                unitData.module_list = filters.module_list\n                unitData.model_list = filters.model_list\n                unitData.model = filters.default_model\n                unitData.module = filters.default_option\n                unitData.model = filters.default_model\n            })\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function initializeControlNetTabComfyUI(\n    controlnet_max_models: number,\n    controlnet_models: string[],\n    preprocessor_list: string[],\n    preprocessorDetail: Record<string, any>\n) {\n    store.maxControlNet = controlnet_max_models || store.maxControlNet\n    // store.controlnetApiVersion = await requestControlNetApiVersion()\n\n    try {\n        const models = controlnet_models\n        store.supportedModels = models || []\n    } catch (e) {\n        console.warn(e)\n    }\n    try {\n        store.supportedPreprocessors = preprocessor_list || []\n\n        store.preprocessorDetail =\n            convertComfyModuleDetailsToPluginModuleDetails(preprocessorDetail)\n    } catch (e) {\n        console.warn(e)\n    }\n    try {\n        store.controlNetUnitData.forEach((unitData) => {\n            unitData.module_list = store.supportedPreprocessors\n            unitData.model_list = store.supportedModels\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction getEnableControlNet(index: number) {\n    if (typeof index == 'undefined')\n        return (\n            store.controlNetUnitData.filter((item) => item.enabled).length > 0\n        )\n    else return store.controlNetUnitData[index || 0].enabled\n}\nasync function mapPluginSettingsToControlNet(plugin_settings: any) {\n    const ps = plugin_settings // for shortness\n    let controlnet_units: any[] = []\n    const controlNetUnits = store.controlNetUnitData\n    async function getControlNetInputImage(index: number) {\n        try {\n            const b_sync_input_image = controlNetUnits[index].auto_image\n            let input_image = controlNetUnits[index].input_image\n            if (\n                b_sync_input_image &&\n                [GenerationModeEnum.Txt2Img].includes(session_store.data.mode)\n            ) {\n                //conditions: 1) txt2img mode 2)auto image on  3)first generation of session\n\n                if (\n                    session_store.data.generation_number === 1 &&\n                    session_store.data.controlnet_input_image === ''\n                ) {\n                    session_store.data.controlnet_input_image =\n                        await io.getImg2ImgInitImage()\n                }\n                if (session_store.data.controlnet_input_image !== '') {\n                    input_image = session_store.data.controlnet_input_image\n                    controlNetUnits[index].input_image = input_image\n                    controlNetUnits[index].selection_info =\n                        plugin_settings.selection_info\n                }\n            }\n            if (\n                b_sync_input_image &&\n                [\n                    GenerationModeEnum.Img2Img,\n                    GenerationModeEnum.Inpaint,\n                    GenerationModeEnum.Outpaint,\n                    GenerationModeEnum.LassoInpaint,\n                ].includes(session_store.data.mode)\n            ) {\n                // img2img mode\n                input_image = session_store.data.init_image\n                controlNetUnits[index].input_image = input_image\n                controlNetUnits[index].selection_info =\n                    plugin_settings.selection_info\n            } else if (b_sync_input_image && controlNetUnits[index].enabled) {\n                //txt2img mode\n            }\n\n            return input_image\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    function getControlNetMask(index: number) {\n        try {\n            if (\n                [\n                    GenerationModeEnum.Txt2Img,\n                    GenerationModeEnum.Img2Img,\n                ].includes(session_store.data.mode)\n            ) {\n                //maskless mode\n            } else {\n                //mask related mode\n                controlNetUnits[index].mask = '' // use the mask from the sd mode\n            }\n            return controlNetUnits[index].mask\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    for (let index = 0; index < store.maxControlNet; index++) {\n        controlnet_units[index] = {\n            enabled: getEnableControlNet(index),\n            input_image: await getControlNetInputImage(index),\n            mask: getControlNetMask(index),\n            module: controlNetUnits[index].module,\n            model: controlNetUnits[index].model,\n            weight: controlNetUnits[index].weight,\n            resize_mode: 'Crop and Resize',\n            lowvram: controlNetUnits[index].lowvram,\n            processor_res: controlNetUnits[index].processor_res || 512,\n            threshold_a: controlNetUnits[index].threshold_a,\n            threshold_b: controlNetUnits[index].threshold_b,\n            // guidance: ,\n            guidance_start: controlNetUnits[index].guidance_start,\n            guidance_end: controlNetUnits[index].guidance_end,\n        }\n        if (store.controlnetApiVersion > 1) {\n            //new controlnet v2\n            controlnet_units[index].control_mode =\n                controlNetUnits[index].control_mode\n            controlnet_units[index].pixel_perfect =\n                controlNetUnits[index].pixel_perfect\n        } else {\n            // old controlnet v1\n            controlnet_units[index].guessmode = controlNetUnits[index].guessmode\n        }\n    }\n\n    const controlnet_payload = {\n        ...ps,\n        controlnet_units, //keep for backward compatibility for now\n        subseed: -1,\n        override_settings: {},\n        override_settings_restore_afterwards: true,\n        alwayson_scripts: {\n            ...(ps?.alwayson_scripts || {}),\n            controlnet: {\n                args: controlnet_units,\n            },\n        },\n    }\n\n    return controlnet_payload\n}\nfunction getControlNetMaxModelsNumber() {\n    return store.maxControlNet\n}\nfunction getUnitsData() {\n    return store.controlNetUnitData\n}\n\nexport function setUnitData(unitData: controlNetUnitData, index: number) {\n    try {\n        store.controlNetUnitData[index] = {\n            ...store.controlNetUnitData[index],\n            ...unitData,\n        }\n\n        if (!unitData?.enabled) {\n            store.controlNetUnitData[index] = {\n                ...store.controlNetUnitData[index],\n                ...DefaultPresetControlNetUnitData,\n            }\n        }\n    } catch (e) {\n        console.error(e)\n    }\n}\nfunction setControlDetectMapSrc(base64: string, index: number) {\n    // store.controlNetUnitData[index].mask = base64\n    store.controlNetUnitData[index].detect_map = base64\n}\nfunction setControlInputImageSrc(base64: string, index: number) {\n    store.controlNetUnitData[index].input_image = base64\n}\nfunction isControlNetModeEnable() {\n    let is_tab_enabled = !store.disableControlNetTab\n\n    let numOfEnabled = 0\n    if (is_tab_enabled) {\n        for (let index = 0; index < store.maxControlNet; index++) {\n            if (getEnableControlNet(index)) {\n                numOfEnabled += 1\n            }\n        }\n    }\n    let is_mode_enabled = is_tab_enabled // could be true\n    if (is_tab_enabled === false || numOfEnabled === 0) {\n        is_mode_enabled = false\n    }\n    return is_mode_enabled\n}\nfunction getModuleDetail() {\n    return store.preprocessorDetail\n}\nexport {\n    requestControlNetModelList,\n    requestControlNetMaxUnits,\n    requestControlNetFiltersKeywords,\n    initializeControlNetTab,\n    initializeControlNetTabComfyUI,\n    getEnableControlNet,\n    mapPluginSettingsToControlNet,\n    getControlNetMaxModelsNumber,\n    getUnitsData,\n    setControlDetectMapSrc,\n    setControlInputImageSrc,\n    isControlNetModeEnable,\n    getModuleDetail,\n    store,\n}\n"
  },
  {
    "path": "typescripts/controlnet/main.tsx",
    "content": "import ReactDOM from 'react-dom/client'\nimport React from 'react'\nimport ControlNetTab from './ControlNetTab'\nimport store from './store'\nimport { versionCompare } from './util'\nimport { Collapsible } from '../util/collapsible'\nimport Locale from '../locale/locale'\nimport { ErrorBoundary } from '../util/errorBoundary'\n\nconst elem = document.getElementById('sp-control_net-tab-page')\nconst elem2 = document.getElementById('sp-control_net-tab-page2')\n\nif (elem) {\n    const root = ReactDOM.createRoot(elem)\n    root.render(\n        <ErrorBoundary>\n            <ControlNetTab appState={store} />\n        </ErrorBoundary>\n    )\n}\n\nif (elem2) {\n    const root = ReactDOM.createRoot(elem2)\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            <div\n                style={{\n                    border: '2px solid #6d6c6c',\n                    padding: '3px',\n                }}\n            >\n                <Collapsible\n                    defaultIsOpen={true}\n                    label={Locale('ControlNet Tab')}\n                >\n                    <div\n                        id=\"controlNetTabParentContainer\"\n                        style={{ marginTop: '10px' }}\n                    >\n                        <ControlNetTab appState={store} />\n                    </div>\n                </Collapsible>\n            </div>\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n}\nfunction scrollToEnabledControlNetUnit() {}\n\n// const button = document.getElementById('scrollToControlNetUnitContainer')!\n// const button_root = ReactDOM.createRoot(button)\n\n// button_root.render(<ErrorBoundary></ErrorBoundary>)\n\nexport { versionCompare }\n"
  },
  {
    "path": "typescripts/controlnet/store.ts",
    "content": "import { observable, reaction } from 'mobx'\nimport { SelectionInfoType } from '../util/ts/enum'\ntype ResizeMode = 'Just Resize' | 'Crop and Resize' | 'Resize and Fill'\nexport const controlnetModes = [\n    'Balanced',\n    'My prompt is more important',\n    'ControlNet is more important',\n] as const\nexport type ControlnetMode = (typeof controlnetModes)[number]\nexport const DefaultControlNetUnitData = {\n    enabled: false,\n    input_image: '',\n    mask: '',\n    detect_map: '',\n    module: '',\n    model: '',\n    weight: 1.0,\n    resize_mode: 'Crop and Resize' as ResizeMode,\n    lowvram: true,\n    processor_res: 512,\n    threshold_a: 0,\n    threshold_b: 0,\n\n    guidance_start: 0,\n    guidance_end: 1,\n    guessmode: false,\n\n    control_mode: 'Balanced' as ControlnetMode,\n    pixel_perfect: true,\n    auto_image: true,\n}\n\nexport const DefaultPresetControlNetUnitData = {\n    enabled: false,\n    // input_image: '',\n    // mask: '',\n    // detect_map: '',\n    module: 'none',\n    model: 'None',\n    filter_keyword: 'All',\n    weight: 1.0,\n\n    resize_mode: 'Crop and Resize' as ResizeMode,\n\n    lowvram: true,\n\n    processor_res: 512,\n    threshold_a: 0,\n    threshold_b: 0,\n\n    guidance_start: 0,\n    guidance_end: 1,\n    guessmode: false,\n\n    control_mode: 'Balanced' as ControlnetMode,\n    pixel_perfect: true,\n    auto_image: true,\n}\n\nexport interface controlNetUnitData {\n    enabled: boolean\n    input_image: string\n    mask: string\n    detect_map: string\n    module_list: string[]\n    model_list: string[]\n    module: string\n    model: string\n    filter_keyword: string\n    weight: number\n    resize_mode: ResizeMode\n    lowvram: boolean\n    processor_res: number\n    threshold_a: number\n    threshold_b: number\n\n    guidance_start: number\n    guidance_end: number\n    guessmode: boolean\n\n    control_mode: ControlnetMode\n    pixel_perfect: boolean\n    auto_image: boolean // sync CtrlNet image with sd input image\n    selection_info: SelectionInfoType\n}\ninterface ControlNetMobxStore {\n    disableControlNetTab: boolean\n    maxControlNet: number\n    controlnetApiVersion: number\n\n    supportedModels: string[]\n    supportedPreprocessors: string[]\n    filterKeywords: string[]\n    preprocessorDetail: { [key: string]: any }\n\n    controlNetUnitData: controlNetUnitData[]\n}\n\nvar ControlNetStore = observable<ControlNetMobxStore>({\n    disableControlNetTab: false,\n    maxControlNet: 0,\n    controlnetApiVersion: 1,\n\n    supportedModels: [],\n    supportedPreprocessors: [],\n    filterKeywords: [],\n    preprocessorDetail: {},\n\n    controlNetUnitData: [],\n})\n\nreaction(\n    () => {\n        return ControlNetStore.controlNetUnitData.map((data) => data.module)\n    },\n    (module_, index) => {\n        ControlNetStore.controlNetUnitData.forEach((data, index) => {\n            const pd = ControlNetStore.preprocessorDetail[module_[index]] || {}\n            const pSlider = pd.sliders || []\n            data.processor_res = pSlider[0]?.value || 512\n            data.threshold_a = pSlider[1]?.value || 0\n            data.threshold_b = pSlider[2]?.value || 0\n        })\n    }\n)\nreaction(\n    () => ControlNetStore.maxControlNet,\n    (maxControlNet) => {\n        ControlNetStore.controlNetUnitData = Array(maxControlNet)\n            .fill(0)\n            .map((v, index) => {\n                return (\n                    ControlNetStore.controlNetUnitData[index] ||\n                    DefaultControlNetUnitData\n                )\n            })\n    }\n)\n\nreaction(\n    () => {\n        return ControlNetStore.controlNetUnitData.map(\n            (data) => data.filter_keyword\n        )\n    },\n    (filter_keyword_, index) => {\n        ControlNetStore.controlNetUnitData.forEach((data, index) => {\n            if (filter_keyword_[index] === 'none') {\n                data.module_list = ControlNetStore.supportedPreprocessors\n                data.model_list = ['None'].concat(\n                    ControlNetStore.supportedModels\n                )\n            }\n        })\n    }\n)\n\nexport default ControlNetStore\n"
  },
  {
    "path": "typescripts/controlnet/util.tsx",
    "content": "export function mapRange(\n    x: number,\n    in_min: number,\n    in_max: number,\n    out_min: number,\n    out_max: number,\n    step: number\n) {\n    return (\n        Math.round(\n            (((x - in_min) * (out_max - out_min)) / (in_max - in_min) +\n                out_min) /\n                step\n        ) * step\n    )\n}\n\nexport function versionCompare(to: string, from: string) {\n    const vTo = to.split('.')\n    const vFrom = from.split('.')\n\n    for (let i = 0; i < Math.max(vTo.length, vFrom.length); i++) {\n        const vFromI = +(vFrom[i] || 0)\n        const vToI = +(vTo[i] || 0)\n        if (isNaN(vFromI) || isNaN(vToI)) {\n            throw new Error(`invalid version ${vTo} or ${vFrom} `)\n        }\n\n        if (vFromI > vToI) {\n            return -1\n        } else if (vFromI < vToI) {\n            return 1\n        }\n    }\n    return 0\n}\n"
  },
  {
    "path": "typescripts/entry.ts",
    "content": "import { configure } from 'mobx'\nconfigure({\n    enforceActions: 'never', // disable mobx warning temporarily\n})\nexport * as control_net from './controlnet/entry'\nexport * as after_detailer_script from './after_detailer/after_detailer'\nexport * as ultimate_sd_upscaler from './ultimate_sd_upscaler/ultimate_sd_upscaler'\nexport * as scripts from './ultimate_sd_upscaler/scripts'\n\nexport * as controlnet_main from './controlnet/main'\nexport * as logger from './util/logger'\nexport * as image_search from './image_search/image_search'\nexport * as history from './history/history'\nexport * as viewer from './viewer/viewer'\nexport { default as viewer_util } from './viewer/viewer_util'\nexport * as session_ts from './session/session'\nexport { store as session_store } from './session/session_store'\nexport { store as sd_tab_store } from './sd_tab/util'\n\nexport * as progress from './session/progress'\nexport * as preview from './viewer/preview'\nexport * as generate from './session/generate'\nexport * as sd_tab_ts from './sd_tab/sd_tab'\nexport * as sd_tab_util from './sd_tab/util'\nexport * as sam from './sam/sam'\nexport * as settings_tab_ts from './settings/settings'\nexport * as one_button_prompt from './one_button_prompt/one_button_prompt'\nexport * as enum_ts from './util/ts/enum'\nexport * as multiPrompts from './multiTextarea'\nexport * as preset from './preset/preset'\nexport * as preset_util from './preset/shared_ui_preset'\nexport * as ui_ts from './util/ts/ui_ts'\nexport * as io_ts from './util/ts/io'\nexport * as tool_bar from './tool_bar/tool_bar'\nexport * as extra_page from './extra_page/extra_page'\nexport * as selection_ts from './util/ts/selection'\nexport * as stores from './stores'\n\nexport { default as lexica } from './lexical/lexical'\nexport * as api_ts from './util/ts/api'\nexport * as comfyui from './comfyui/comfyui'\nexport { toJS } from 'mobx'\nexport { default as node_fs } from 'fs'\nexport { default as comfyui_util } from './comfyui/util'\nexport { default as comfyui_main_ui } from './comfyui/main_ui'\n\nexport { default as comfyapi } from './comfyui/comfyapi'\n"
  },
  {
    "path": "typescripts/extra_page/extra_page.tsx",
    "content": "import { observer } from 'mobx-react'\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { Collapsible } from '../util/collapsible'\nimport { GenerateButtons } from '../session/generate'\nimport { AStore } from '../main/astore'\nimport { SpMenu, SpSlider } from '../util/elements'\nimport { mapRange } from '../controlnet/util'\nimport { requestGetUpscalers } from '../util/ts/sdapi'\n\nexport const store = new AStore({\n    upscaling_resize: 2,\n    upscaler_list: [] as string[],\n    upscaler_1: '',\n    upscaler_2: '',\n    resize_mode: 0,\n    show_extras_results: 0,\n    gfpgan_visibility: 0,\n    codeformer_visibility: 0,\n    codeformer_weight: 0,\n    upscaling_resize_w: 0,\n    upscaling_resize_h: 0,\n    upscaling_crop: true,\n    extras_upscaler_2_visibility: 0,\n    upscale_first: false,\n})\n\nexport async function refreshExtraUpscalers() {\n    try {\n        const upscalers = await requestGetUpscalers()\n        if (upscalers) {\n            store.data.upscaler_list = upscalers.map(\n                (upscaler: { name: any }) => upscaler.name\n            )\n        }\n    } catch (e) {\n        console.error(e)\n    }\n}\n@observer\nexport class ExtraPage extends React.Component {\n    componentDidMount(): void {}\n\n    render(): React.ReactNode {\n        return (\n            <div>\n                <div style={{ paddingBottom: '5px' }}>\n                    <SpSlider\n                        style={{ display: 'block' }}\n                        show-value=\"false\"\n                        id=\"slUpscaleSize\"\n                        min=\"10\"\n                        max=\"80\"\n                        value={store.data.upscaling_resize * 10}\n                        title=\"Resize scale of current selection size\"\n                        onInput={(evt: any) => {\n                            store.data.upscaling_resize = mapRange(\n                                evt.target.value,\n                                10,\n                                80,\n                                1,\n                                8,\n                                0.01\n                            )\n                        }}\n                    >\n                        <sp-label slot=\"label\">Resize</sp-label>\n                        <sp-label\n                            class=\"labelNumber\"\n                            slot=\"label\"\n                            id=\"lUpscaleSize\"\n                        >\n                            {store.data.upscaling_resize.toFixed(2)}\n                        </sp-label>\n                    </SpSlider>\n                </div>\n                <GenerateButtons></GenerateButtons>\n\n                <div\n                    id=\"progressContainerUpscale\"\n                    style={{ paddingBottom: '5px' }}\n                >\n                    <sp-label slot=\"label\" class=\"lProgressLabel\">\n                        No work in progress\n                    </sp-label>\n                </div>\n                <div style={{ paddingBottom: '5px' }}>\n                    <sp-label\n                        class=\"title\"\n                        style={{ width: '60px', display: 'inline-block' }}\n                    >\n                        Upscaler 1:\n                    </sp-label>\n                    <SpMenu\n                        size=\"m\"\n                        title=\"Upscaler 1\"\n                        items={store.data.upscaler_list}\n                        label_item=\"Select an Upscaler Model\"\n                        selected_index={store.data.upscaler_list.indexOf(\n                            store.data.upscaler_1\n                        )}\n                        onChange={(id: any, value: any) => {\n                            store.data.upscaler_1 = value.item\n                        }}\n                    ></SpMenu>\n\n                    <div></div>\n                    <sp-label\n                        class=\"title\"\n                        style={{ width: '60px', display: 'inline-block' }}\n                    >\n                        Upscaler 2:\n                    </sp-label>\n                    <SpMenu\n                        size=\"m\"\n                        title=\"Upscaler 2\"\n                        items={store.data.upscaler_list}\n                        label_item=\"Select an Upscaler Model\"\n                        selected_index={store.data.upscaler_list.indexOf(\n                            store.data.upscaler_2\n                        )}\n                        onChange={(id: any, value: any) => {\n                            store.data.upscaler_2 = value.item\n                        }}\n                    ></SpMenu>\n                </div>\n                <div style={{ paddingBottom: '5px' }}>\n                    <SpSlider\n                        style={{ display: 'block' }}\n                        show-value=\"false\"\n                        id=\"slUpscaler2Visibility\"\n                        min=\"0\"\n                        max=\"10\"\n                        value={store.data.extras_upscaler_2_visibility * 10}\n                        onInput={(evt: any) => {\n                            store.data.extras_upscaler_2_visibility =\n                                evt.target.value / 10\n                        }}\n                    >\n                        <sp-label\n                            class=\"title\"\n                            style={{ width: '110px', display: 'inline-block' }}\n                            slot=\"label\"\n                        >\n                            Upscaler 2 visibility:\n                        </sp-label>\n                        <sp-label\n                            style={{ display: 'inline-block' }}\n                            class=\"labelNumber\"\n                            slot=\"label\"\n                            id=\"lUpscaler2Visibility\"\n                        >\n                            {store.data.extras_upscaler_2_visibility.toFixed(2)}\n                        </sp-label>\n                    </SpSlider>\n                </div>\n                <div style={{ paddingBottom: '5px' }}>\n                    <SpSlider\n                        style={{ display: 'block' }}\n                        show-value=\"false\"\n                        id=\"slGFPGANVisibility\"\n                        min=\"0\"\n                        max=\"10\"\n                        value={store.data.gfpgan_visibility * 10}\n                        onInput={(evt: any) => {\n                            store.data.gfpgan_visibility = evt.target.value / 10\n                        }}\n                    >\n                        <sp-label\n                            class=\"title\"\n                            style={{ width: '110px', display: 'inline-block' }}\n                            slot=\"label\"\n                        >\n                            GFPGAN visibility:\n                        </sp-label>\n                        <sp-label\n                            style={{ display: 'inline-block' }}\n                            class=\"labelNumber\"\n                            slot=\"label\"\n                            id=\"lGFPGANVisibility\"\n                        >\n                            {store.data.gfpgan_visibility.toFixed(2)}\n                        </sp-label>\n                    </SpSlider>\n                </div>\n                <div style={{ paddingBottom: '5px' }}>\n                    <SpSlider\n                        style={{ display: 'block' }}\n                        show-value=\"false\"\n                        id=\"slCodeFormerVisibility\"\n                        min=\"0\"\n                        max=\"10\"\n                        value={store.data.codeformer_visibility * 10}\n                        onInput={(evt: any) => {\n                            store.data.codeformer_visibility =\n                                evt.target.value / 10\n                        }}\n                    >\n                        <sp-label\n                            class=\"title\"\n                            style={{ width: '110px', display: 'inline-block' }}\n                            slot=\"label\"\n                        >\n                            CodeFormer visibility:\n                        </sp-label>\n                        <sp-label\n                            style={{ display: 'inline-block' }}\n                            class=\"labelNumber\"\n                            slot=\"label\"\n                            id=\"lCodeFormerVisibility\"\n                        >\n                            {store.data.codeformer_visibility.toFixed(2)}\n                        </sp-label>\n                    </SpSlider>\n                </div>\n                <div style={{ paddingBottom: '5px' }}>\n                    <SpSlider\n                        style={{ display: 'block' }}\n                        show-value=\"false\"\n                        id=\"slCodeFormerWeight\"\n                        min=\"0\"\n                        max=\"10\"\n                        value={store.data.codeformer_weight * 10}\n                        onInput={(evt: any) => {\n                            store.data.codeformer_weight = evt.target.value / 10\n                        }}\n                    >\n                        <sp-label\n                            class=\"title\"\n                            style={{ width: '110px', display: 'inline-block' }}\n                            slot=\"label\"\n                        >\n                            CodeFormer weight:\n                        </sp-label>\n                        <sp-label\n                            style={{ display: 'inline-block' }}\n                            class=\"labelNumber\"\n                            slot=\"label\"\n                            id=\"lCodeFormerWeight\"\n                        >\n                            {store.data.codeformer_weight.toFixed(2)}\n                        </sp-label>\n                    </SpSlider>\n                </div>\n            </div>\n        )\n    }\n}\n\nconst containers = document.querySelectorAll('.extraPageContainer')!\n\ncontainers.forEach((container) => {\n    const root = ReactDOM.createRoot(container)\n\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible defaultIsOpen={true} label={'Extra Page'}>\n                    <ExtraPage />\n                </Collapsible>\n            </div>\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n})\n"
  },
  {
    "path": "typescripts/globalstore.ts",
    "content": "import { observable } from 'mobx'\nimport { host } from 'uxp'\n\ninterface GlobalStore {\n    Locale: 'zh_CN' | 'en_US'\n}\n\nconst initialLocale =\n    localStorage.getItem('last_selected_locale') || host.uiLocale\nvar globalStore = observable<GlobalStore>({\n    Locale: initialLocale == 'zh_CN' ? initialLocale : 'en_US',\n})\n\nexport default globalStore\n"
  },
  {
    "path": "typescripts/history/history.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { observer } from 'mobx-react'\nimport { AStore, toJS } from '../main/astore'\nimport { Grid } from '../util/grid'\nimport { io, python_replacement, settings_tab } from '../util/oldSystem'\nimport { MoveToCanvasSvg, PenSvg } from '../util/elements'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport Locale from '../locale/locale'\nimport { addWithHistory } from '../viewer/viewer'\nimport { Collapsible } from '../util/collapsible'\n//@ts-ignore\nimport { storage } from 'uxp'\nimport { _arrayBufferToBase64 } from '../util/ts/io'\nimport { sd_tab_store } from '../stores'\nimport { postPng } from '../util/ts/api'\nimport { setPrompt } from '../multiTextarea'\nimport sd_tab_util from '../sd_tab/util'\n\ndeclare let g_ui_settings_object: any\nexport const store = new AStore({\n    images: [] as string[], //full resloution images\n    thumbnails: [] as string[], //small resolution images useful to preview inside html\n    refresh: false,\n    width: 50,\n    height: 50,\n    scale: 1,\n    metadata_jsons: [] as any[],\n})\n\nasync function getMetaDataForOutputEntry(doc_entry: any, output_entry: any) {\n    const json_file_name = `${output_entry.name.split('.')[0]}.json`\n\n    try {\n        const json_entry = await doc_entry.getEntry(json_file_name)\n        if (json_entry) {\n            // await json_entry.read()\n\n            const json = JSON.parse(\n                await json_entry.read({\n                    format: storage.formats.utf8,\n                })\n            )\n            return json\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n    return {}\n}\n\nasync function getOutputImagesEntries(doc_entry: any) {\n    let entries = await doc_entry.getEntries()\n    const output_images_entries = entries.filter(\n        (e: any) => e.isFile && e.name.toLowerCase().includes('.png') // must be a file and has the of the type .png\n    )\n    console.log('output_images_entries: ', output_images_entries)\n    // .forEach((e) => console.log(e.name))\n    return output_images_entries\n}\n\nasync function loadHistory(payload: any) {\n    //  {'image_paths','metadata_setting'}\n    const history: any = {}\n\n    // const uniqueDocumentId = payload['uniqueDocumentId']\n    // const uniqueDocumentId = await getUniqueDocumentId()\n\n    const uuid = await io.getUniqueDocumentId()\n    const doc_entry = await io.IOFolder.getDocFolder(uuid)\n    const output_images_entries = await getOutputImagesEntries(doc_entry)\n    history['image_paths'] = []\n    history['metadata_jsons'] = []\n    history['base64_images'] = []\n    for (const output_entry of output_images_entries) {\n        history['image_paths'].push(output_entry.name)\n        const metadata_json = await getMetaDataForOutputEntry(\n            doc_entry,\n            output_entry\n        )\n        history['metadata_jsons'].push(metadata_json)\n\n        const arrayBuffer = await output_entry.read({\n            format: storage.formats.binary,\n        })\n        const base64_image = _arrayBufferToBase64(arrayBuffer) //convert the buffer to base64\n\n        // const base64 =\n        history['base64_images'].push(base64_image)\n    }\n\n    //     image_paths = glob.glob(f'./output/{uniqueDocumentId}/*.png')\n    //     settings_paths = glob.glob(f'./output/{uniqueDocumentId}/*.json')#note: why is we are not using settings_paths?\n    //     print(\"loadHistory: image_paths:\", image_paths)\n\n    //     history['image_paths'] = image_paths\n    //     history['metadata_jsons'] = []\n    //     history['base64_images'] = []\n    //     for image_path in image_paths:\n    //         print(\"image_path: \", image_path)\n    //         metadata_dict = metadata_to_json.createMetadataJsonFileIfNotExist(image_path)\n    //         history['metadata_jsons'].append(metadata_dict)\n\n    //         img = Image.open(image_path)\n    //         base64_image = img_2_b64(img)\n    //         history['base64_images'].append(base64_image)\n\n    // except:\n\n    //     print(f'{request}')\n\n    // #reverse the order so that newer generated images path will be shown first\n\n    // history['image_paths'].reverse()\n    // history['metadata_jsons'].reverse()\n    // history['base64_images'].reverse()\n    return {\n        image_paths: history['image_paths'],\n        metadata_jsons: history['metadata_jsons'],\n        base64_images: history['base64_images'],\n    }\n}\n\nasync function moveHistoryImageToLayer(\n    base64_image: string,\n    selection_info: any,\n    metadata: any\n) {\n    try {\n        // const to_x = selection_info?.left\n        // const to_y = selection_info?.top\n        // const width = selection_info?.width\n        // const height = selection_info?.height\n        // await io.IO.base64ToLayer(\n        //     base64_image,\n        //     'History Image',\n        //     to_x,\n        //     to_y,\n        //     width,\n        //     height\n        // )\n\n        const layer = await addWithHistory(\n            base64_image,\n            metadata?.expanded_mask ?? void 0,\n            selection_info,\n            metadata.mode\n        )\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction historyMetadataToPreset(metadata: any) {}\nfunction getHistoryMetadata(metadata_json: any) {\n    //auto fill the ui with metadata\n    // const metadata_json = JSON.parse(img.dataset.metadata_json_string)\n\n    console.log('metadata_json: ', metadata_json)\n\n    //extract auto_metadata into the preset metadata\n    function convertAutoMetadataToPreset(metadata_json: any) {\n        metadata_json['seed'] = metadata_json?.auto_metadata?.Seed\n    }\n    convertAutoMetadataToPreset(metadata_json)\n\n    const b_use_original_prompt = settings_tab.getUseOriginalPrompt()\n    if (b_use_original_prompt) {\n        metadata_json['prompt'] = metadata_json?.original_prompt\n            ? metadata_json['original_prompt']\n            : metadata_json['prompt']\n\n        metadata_json['negative_prompt'] =\n            metadata_json?.original_negative_prompt\n                ? metadata_json['original_negative_prompt']\n                : metadata_json['negative_prompt']\n    } else {\n        metadata_json['prompt'] = metadata_json['prompt']\n\n        metadata_json['negative_prompt'] = metadata_json['negative_prompt']\n    }\n    // document.querySelector('#historySeedLabel').textContent =\n    //     metadata_json?.seed\n\n    g_ui_settings_object.autoFillInSettings(toJS(metadata_json))\n}\n\ninterface Auto111Metadata {\n    prompt?: string\n    negative_prompt?: string\n    Steps?: string\n    Sampler?: string\n    'CFG scale'?: string\n    Seed?: string\n    Size?: string\n    'Model hash'?: string\n    Model?: string\n    'Denoising strength'?: string\n    'Mask blur'?: string\n    Version?: string\n}\nfunction ChangeSettingsFromAuto1111Metadata(metadata: Auto111Metadata) {\n    if (metadata?.prompt)\n        setPrompt({\n            positive: metadata.prompt,\n            negative: metadata?.negative_prompt,\n        })\n\n    if (metadata?.Steps) sd_tab_util.store.data.steps = Number(metadata.Steps)\n\n    if (metadata?.Sampler)\n        sd_tab_util.store.data.sampler_name = metadata.Sampler\n    if (metadata?.['CFG scale'])\n        sd_tab_util.store.data.cfg = Number(metadata['CFG scale'])\n    if (metadata?.Seed) sd_tab_util.store.data.seed = metadata.Seed\n    if (metadata?.Size)\n        [sd_tab_util.store.data.width, sd_tab_util.store.data.height] =\n            metadata.Size.split('x').map((dim) => Number(dim))\n    if (metadata?.['Denoising strength'])\n        sd_tab_util.store.data.denoising_strength = Number(\n            metadata['Denoising strength']\n        )\n}\ninterface CombinedElement {\n    thumbnail: string\n    image: string\n    metadata_json: any\n}\n\nfunction combineAndSortArrays(\n    thumbnails: string[],\n    images: string[],\n    metadata_jsons: any[]\n) {\n    // Set session_id to 0 if undefined\n    metadata_jsons.forEach((metadata) => {\n        if (metadata.session_id === undefined) {\n            metadata.session_id = 0\n        }\n    })\n\n    // Combine arrays into one array of objects\n    const combinedArray: CombinedElement[] = thumbnails.map(\n        (thumbnail, index) => ({\n            thumbnail,\n            image: images[index],\n            metadata_json: metadata_jsons[index],\n        })\n    )\n\n    // Sort combined array by session_id\n    combinedArray.sort(\n        (a, b) =>\n            // a.metadata_json.session_id.localeCompare(b.metadata_json.session_id)\n            a.metadata_json.session_id - b.metadata_json.session_id\n    )\n\n    return combinedArray\n}\n\nfunction segmentCombinedArray(combinedArray: CombinedElement[]) {\n    const segmentedArray: CombinedElement[][] = []\n    let currentSessionId = combinedArray[0].metadata_json.session_id\n    let currentSegment: CombinedElement[] = []\n\n    for (const element of combinedArray) {\n        if (element.metadata_json.session_id === currentSessionId) {\n            currentSegment.push(element)\n        } else {\n            segmentedArray.push(currentSegment)\n            currentSessionId = element.metadata_json.session_id\n            currentSegment = [element]\n        }\n    }\n\n    if (currentSegment.length > 0) {\n        segmentedArray.push(currentSegment)\n    }\n\n    return segmentedArray\n}\n\n@observer\nclass History extends React.Component<{}> {\n    componentDidMount(): void {\n        const loadHistoryBtn = document.querySelector('#btnLoadHistory')\n        const clearHistoryCacheBtn = document.getElementById(\n            'btnClearHistoryCache'\n        )\n        loadHistoryBtn?.addEventListener('click', this.onLoadHistory)\n\n        clearHistoryCacheBtn?.addEventListener(\n            'click',\n            this.onClearHistoryCache\n        )\n    }\n    componentWillUnmount(): void {\n        const loadHistoryBtn = document.querySelector('#btnLoadHistory')\n        const clearHistoryCacheBtn = document.getElementById(\n            'btnClearHistoryCache'\n        )\n        loadHistoryBtn?.removeEventListener('click', this.onLoadHistory)\n        clearHistoryCacheBtn?.removeEventListener(\n            'click',\n            this.onClearHistoryCache\n        )\n    }\n\n    onClearHistoryCache() {\n        store.updateProperty('images', [])\n        store.updateProperty('thumbnails', [])\n        store.updateProperty('metadata_jsons', [])\n    }\n    async onLoadHistory() {\n        try {\n            const uniqueDocumentId = await io.getUniqueDocumentId()\n            const { image_paths, metadata_jsons, base64_images } =\n                await loadHistory(uniqueDocumentId)\n\n            store.updateProperty('images', base64_images)\n            store.updateProperty('thumbnails', base64_images)\n            store.updateProperty('metadata_jsons', metadata_jsons)\n        } catch (e) {\n            console.warn(`loadHistory warning: ${e}`)\n        }\n    }\n    createGrids(\n        thumbnails: string[],\n        images: string[],\n        metadata_jsons: string[]\n    ) {\n        const combinedArray = combineAndSortArrays(\n            thumbnails,\n            images,\n            metadata_jsons\n        )\n        const sessionArray = segmentCombinedArray(combinedArray)\n        // console.log('sessionArray:', sessionArray)\n        const GridsComponent = sessionArray.map(\n            (session: CombinedElement[], i) => {\n                const thumbnails = session.map(\n                    (generated_image_data: CombinedElement, j) => {\n                        return generated_image_data.thumbnail\n                    }\n                )\n                const images = session.map(\n                    (generated_image_data: CombinedElement, j) => {\n                        return generated_image_data.image\n                    }\n                )\n                const metadata_jsons = session.map(\n                    (generated_image_data: CombinedElement, j) => {\n                        return generated_image_data.metadata_json\n                    }\n                )\n                return (\n                    <div\n                        key={i}\n                        style={{ border: '2px solid #6d6c6c', padding: '3px' }}\n                    >\n                        <sp-label style={{}}>\n                            {metadata_jsons?.[0]?.session_id}{' '}\n                            {metadata_jsons?.[0]?.mode}\n                        </sp-label>\n                        {this.createGrid(thumbnails, images, metadata_jsons)}\n                    </div>\n                )\n                // return createGrid(thumbnails, images, metadata_jsons)\n            }\n        )\n        return GridsComponent\n    }\n    createGrid(thumbnails: string[], images: string[], metadata_jsons: any[]) {\n        return (\n            <Grid\n                thumbnails={thumbnails?.map((base64: string) =>\n                    base64\n                        ? 'data:image/png;base64,' + base64\n                        : 'https://source.unsplash.com/random'\n                )}\n                width={store.data.width}\n                height={store.data.height}\n                action_buttons={[\n                    {\n                        ComponentType: PenSvg,\n                        callback: (index: number) => {\n                            try {\n                                // console.log(\n                                //     store.toJsFunc().data.metadata_jsons[index]\n                                // )\n                                getHistoryMetadata(metadata_jsons[index])\n                            } catch (e) {\n                                console.warn(e)\n                            }\n                        },\n                        title: Locale('Copy Metadata to Settings'),\n                    },\n                    {\n                        ComponentType: MoveToCanvasSvg,\n                        callback: (index: number) => {\n                            moveHistoryImageToLayer(\n                                images[index],\n                                metadata_jsons[index]['selection_info'],\n                                metadata_jsons[index]\n                            )\n                        },\n                        title: Locale('Copy Image to Canvas'),\n                    },\n                ]}\n            ></Grid>\n        )\n    }\n\n    render(): React.ReactNode {\n        return (\n            <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible defaultIsOpen={true} label={Locale('History')}>\n                    <div style={{ width: '100%' }}>\n                        {/* {store.data.refresh} */}\n                        <sp-slider\n                            min={85}\n                            max={300}\n                            onInput={(\n                                event: React.ChangeEvent<HTMLInputElement>\n                            ) => {\n                                const new_value = event.target.value\n                                store.updateProperty('height', new_value)\n                                store.updateProperty('width', new_value)\n                            }}\n                            show-value=\"true\"\n                            value={100}\n                        >\n                            <sp-label slot=\"label\">Image Size:</sp-label>\n                        </sp-slider>\n                        <div>\n                            <button\n                                style={{ marginBottom: '3px' }}\n                                className=\"btnSquare\"\n                                onClick={async () => {\n                                    try {\n                                        const response_json = await postPng()\n                                        if (\n                                            response_json?.metadata?.parameters\n                                        ) {\n                                            const auto_metadata =\n                                                python_replacement.convertMetadataToJson(\n                                                    response_json.metadata\n                                                        .parameters\n                                                )\n                                            console.log(\n                                                'auto_metadata: ',\n                                                auto_metadata\n                                            )\n                                            ChangeSettingsFromAuto1111Metadata(\n                                                auto_metadata\n                                            )\n                                        }\n                                    } catch (e) {\n                                        console.warn(e)\n                                    }\n                                }}\n                            >\n                                Load Metadata from Image\n                            </button>\n                        </div>\n                        <div>\n                            <button\n                                className=\"btnSquare\"\n                                id=\"btnLoadHistory\"\n                                style={{ marginRight: '3px' }}\n                            >\n                                Load Previous Generations\n                            </button>\n                            <button\n                                className=\"btnSquare\"\n                                id=\"btnClearHistoryCache\"\n                            >\n                                Clear Results\n                            </button>\n                        </div>\n                        {store.data.metadata_jsons.length > 0\n                            ? this.createGrids(\n                                  store.data.thumbnails,\n                                  store.data.images,\n                                  store.data.metadata_jsons\n                              )\n                            : void 0}\n                    </div>\n                </Collapsible>\n            </div>\n        )\n    }\n}\n\nconst gridContainerNode = document.getElementById('historyImagesContainer')!\nconst gridRoot = ReactDOM.createRoot(gridContainerNode)\n\ngridRoot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <History></History>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/image_search/image_search.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { observer } from 'mobx-react'\nimport { AStore } from '../main/astore'\nimport { Grid } from '../util/grid'\nimport { MoveToCanvasSvg } from '../util/elements'\nimport { io } from '../util/oldSystem'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { urlToCanvas } from '../util/ts/general'\n\nexport const store = new AStore({\n    images: [],\n    thumbnails: [],\n    refresh: false,\n    width: 50,\n    height: 50,\n})\n\nconst ImageSearch = observer(() => {\n    console.log('rendered')\n    return (\n        <div>\n            <sp-slider\n                min={85}\n                max={300}\n                onInput={(event: React.ChangeEvent<HTMLInputElement>) => {\n                    const new_value = event.target.value\n                    store.updateProperty('height', new_value)\n                    store.updateProperty('width', new_value)\n                }}\n                show-value=\"true\"\n            >\n                <sp-label slot=\"label\">Image Size:</sp-label>\n            </sp-slider>\n            <Grid\n                // thumbnails_data={store.data.images}\n                thumbnails={store.data.thumbnails}\n                width={store.data.width}\n                height={store.data.height}\n                action_buttons={[\n                    {\n                        ComponentType: MoveToCanvasSvg,\n                        callback: (index: number) => {\n                            urlToCanvas(\n                                store.data.images[index],\n                                'search_image_temp.png'\n                            )\n                        },\n                        title: 'Copy Image to Canvas',\n                    },\n                ]}\n            ></Grid>\n        </div>\n    )\n})\n\nconst gridContainerNode = document.getElementById(\n    'divImageSearchImagesContainer'\n    // 'search_second_panel'\n)!\nconst gridRoot = ReactDOM.createRoot(gridContainerNode)\n\nlet images: string[] = []\ngridRoot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <ImageSearch></ImageSearch>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/lexical/lexical.tsx",
    "content": "//TODO: delete lexical_tab.js and lexica tab from html\nimport { observer } from 'mobx-react'\nimport React, { TextareaHTMLAttributes } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { AStore } from '../main/astore'\nimport {\n    ImageSearchSvg,\n    MoveToCanvasSvg,\n    PenSvg,\n    SpTextfield,\n} from '../util/elements'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { requestGet } from '../util/ts/api'\nimport { Grid } from '../util/grid'\nimport { urlToCanvas } from '../util/ts/general'\nimport sd_tab_util from '../sd_tab/util'\nimport { setPrompt } from '../multiTextarea'\nimport { Collapsible } from '../util/collapsible'\nimport Locale from '../locale/locale'\n\ninterface LexicaItem {\n    id: string\n    gallery: string\n    src: string\n    srcSmall: string\n    prompt: string\n    width: number\n    height: number\n    seed: string\n    grid: boolean\n    model: string\n    guidance: number\n    promptid: string\n    nsfw: boolean\n}\n\nexport const store = new AStore({\n    search_query: 'cute cats' as string,\n    lexica_items: [] as LexicaItem[],\n    height: 100,\n    width: 100,\n    thumbnails: [] as string[],\n    images: [] as string[],\n    lexica_prompt: '' as string,\n    textarea_position: 'static' as 'static' | 'fixed',\n    textarea_display: 'none' as 'none' | undefined,\n})\n\nasync function requestLexica(search_query: string) {\n    const lexica_url = `https://lexica.art/api/v1/search?q=${search_query}`\n    const url_encoded = encodeURI(lexica_url)\n    const result = await requestGet(url_encoded)\n    console.log('result:', result)\n    return result\n}\n\nasync function loadSettingsToUI(lexica_item: LexicaItem) {\n    try {\n        setPrompt({ positive: lexica_item.prompt })\n        sd_tab_util.store.data.width = lexica_item.width\n        sd_tab_util.store.data.height = lexica_item.height\n        sd_tab_util.store.data.seed = lexica_item.seed\n        sd_tab_util.store.data.cfg = lexica_item.guidance\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nconst windowEventListener = document\n    .querySelector('#search_second_panel')!\n    .addEventListener('scroll', () => {\n        const taLexicaPromptElement = document.querySelector(\n            '#lexicaPrompt'\n        ) as any\n        const originalPosition = taLexicaPromptElement.offsetTop\n\n        const currentPosition =\n            //@ts-ignore\n            document.querySelectorAll('.lexicaContainer')[0].offsetTop\n\n        store.data.textarea_display = 'none'\n    })\n\nfunction onThumbnailClick(lexical_item: LexicaItem) {\n    store.data.lexica_prompt = lexical_item.prompt\n\n    const taLexicaPromptElement = document.querySelector('#lexicaPrompt') as any\n    const originalPosition = taLexicaPromptElement.offsetTop\n\n    const containerPosition =\n        //@ts-ignore\n        document.querySelectorAll('.lexicaContainer')[0].offsetTop\n\n    const isScrolledPast = containerPosition < originalPosition\n\n    store.data.textarea_display = undefined\n}\n\nasync function searchForSimilarImage(lexica_item: LexicaItem) {\n    try {\n        store.data.search_query = lexica_item.src\n        const result_json = await requestLexica(store.data.search_query)\n\n        const lexica_items = result_json.images\n\n        store.data.lexica_items = lexica_items\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n@observer\nexport class Lexical extends React.Component {\n    componentDidMount(): void {}\n    componentWillUnmount(): void {}\n\n    render() {\n        return (\n            <div>\n                <div className=\"subTabOptionsContainer\"></div>\n\n                <div className=\"flexContainer\">\n                    <sp-label slot=\"label\">\n                        Explore Lexica for prompts and inspiration\n                    </sp-label>\n                </div>\n                <div></div>\n                <div>\n                    {/* <sp-label slot=\"label\">Search:</sp-label> */}\n                    <sp-textfield\n                        id=\"LexicaSearchField\"\n                        type=\"text\"\n                        // placeholder=\"cute cats\"\n                        value={store.data.search_query}\n                        onInput={(event: any) => {\n                            store.data.search_query = event.target.value\n                        }}\n                    ></sp-textfield>\n\n                    <button\n                        className=\"btnSquare search-button\"\n                        id=\"btnSearchLexica\"\n                        title=\"user prompt(text) to Search Lexica\"\n                        onClick={async () => {\n                            const search_query = store.data.search_query\n                            const result_json = await requestLexica(\n                                search_query\n                            )\n\n                            const lexica_items = result_json.images\n                            store.data.lexica_items = lexica_items\n                        }}\n                    ></button>\n\n                    <button\n                        className=\"btnSquare reverse_image_serach\"\n                        id=\"btnReverseSearchLexica\"\n                        title=\"User the selected area (image) on canvas to Search Lexica\"\n                    ></button>\n                </div>\n                <sp-textarea\n                    id=\"lexicaPrompt\"\n                    style={{\n                        marginBottom: '3px',\n                        position: 'fixed',\n                        display: store.data.textarea_display,\n                    }}\n                    value={store.data.lexica_prompt}\n                ></sp-textarea>\n                <div className=\"viewer-container\" id=\"divLexicaImagesContainer\">\n                    <img\n                        className=\"history-image\"\n                        id=\"history_image_test\"\n                        data-metadata_json_string='{\"a\":1}'\n                        src=\"https://source.unsplash.com/random\"\n                    />\n                </div>\n                <div>\n                    <sp-slider\n                        min={85}\n                        max={300}\n                        onInput={(\n                            event: React.ChangeEvent<HTMLInputElement>\n                        ) => {\n                            const new_value = event.target.value\n                            store.updateProperty('height', new_value)\n                            store.updateProperty('width', new_value)\n                        }}\n                        show-value=\"true\"\n                    >\n                        <sp-label slot=\"label\">Image Size:</sp-label>\n                    </sp-slider>\n                    <Grid\n                        thumbnails={store.data.lexica_items.map(\n                            (item: LexicaItem) => {\n                                return item.srcSmall\n                            }\n                        )}\n                        width={store.data.width}\n                        height={store.data.height}\n                        callback={(index: number, evt: any) => {\n                            onThumbnailClick(store.data.lexica_items[index])\n                        }}\n                        action_buttons={[\n                            {\n                                ComponentType: MoveToCanvasSvg,\n                                callback: (index: number) => {\n                                    urlToCanvas(\n                                        store.data.lexica_items[index].src,\n                                        'lexica.png'\n                                    )\n                                },\n                                title: 'Copy Image to Canvas',\n                            },\n                            {\n                                ComponentType: PenSvg,\n                                callback: (index: number) => {\n                                    loadSettingsToUI(\n                                        store.data.lexica_items[index]\n                                    )\n                                },\n                                title: 'Apply Settings',\n                            },\n                            {\n                                ComponentType: ImageSearchSvg,\n                                callback: (index: number) => {\n                                    searchForSimilarImage(\n                                        store.data.lexica_items[index]\n                                    )\n                                },\n                                title: 'Search For Similar Images',\n                            },\n                        ]}\n                    ></Grid>\n                </div>\n            </div>\n        )\n    }\n}\n\nconst containers = document.querySelectorAll('.lexicaContainer')!\n\ncontainers.forEach((container) => {\n    const root = ReactDOM.createRoot(container)\n\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible defaultIsOpen={true} label={Locale('Lexical')}>\n                    <Lexical></Lexical>\n                </Collapsible>\n            </div>\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n})\n\nexport default {\n    store: store,\n}\n"
  },
  {
    "path": "typescripts/locale/locale-for-old-html.ts",
    "content": "import { reaction } from 'mobx'\nimport globalStore from '../globalstore'\nimport Locale from './locale'\n\nconst elemSelectorForLocale = {\n    // tab bar\n    '#sp-stable-diffusion-ui-tab sp-label': 'Stable Diffusion',\n    '#sp-viewer-tab sp-label': 'Viewer',\n    '#sp-control_net-tab sp-label': 'ControlNet',\n    // '#sp-history-tab sp-label': 'History',\n    // '#sp-lexica-tab sp-label': 'Lexica',\n    '#sp-image_search-tab sp-label': 'Image Search',\n    '#sp-prompts-library-tab sp-label': 'Prompts library',\n    '#sp-horde-tab sp-label': 'Horde',\n    '#sp-extras-tab sp-label': 'Extras',\n    '#sp-presets-tab sp-label': 'Presets',\n    '#sp-settings-tab sp-label': 'Settings',\n\n    // viewer tab\n    '#rgSubTab .rbSubTab': 'Viewer',\n    '#rbHistoryTab': 'History',\n    '#rbImageSearch': 'Image Search',\n    '#rbPromptsLibrary': 'Prompts Library',\n    '#rbLexica': 'Lexica',\n    '#viewerSubTab .flexContainer sp-label':\n        'View your generated images on the canvas',\n    // '#btnSetMaskViewer': 'Set Mask',\n    // '#btnSetInitImageViewer': 'Set Init Image',\n    '#btnInterruptViewer': 'Interrupt',\n    // '#btnSelectionArea': 'Selection Area',\n\n    // extra tab\n    // '#slThumbnailSize sp-label': 'Thumbnail Size',\n    '#chSquareThumbnail': 'Square 1:1',\n    '#btnGenerateUpscale': 'Generate upscale',\n    '#btnInterruptUpscale': 'Interrupt',\n    '#progressContainerUpscale sp-label': 'No work in progress',\n    '#slUpscaler2Visibility .title': 'Upscaler 2 visibility',\n    '#slGFPGANVisibility .title': 'GFPGAN visibility',\n    '#slCodeFormerVisibility .title': 'CodeFormer visibility',\n    '#slCodeFormerWeight .title': 'CodeFormer weight',\n\n    // sd tab\n    '#pViewerProgressBar .lProgressLabel': 'Progress...',\n    '#btnRefreshModels': 'Refresh',\n    '#btnUpdate': 'Update',\n    '#chUsePromptShortcut': 'prompt shortcut',\n    '#btnInterrupt': 'Interrupt',\n    '#bSetInitImage': 'Image',\n    '#bSetInitImageMask': 'Mask',\n    '#batchNumberSdUiTabContainer sp-label': 'Batch Size',\n    '#batchCountSdUiTabContainer sp-label': 'Batch count',\n    '#rbSelectionModeLabel': 'Selection Mode',\n    '#selectionModeGroup [value=ratio]': 'ratio',\n    '#selectionModeGroup [value=precise]': 'precise',\n    '#selectionModeGroup [value=ignore]': 'ignore',\n    '#slCfgScale .title': 'CFG Scale',\n    '#slImageCfgScale .title': 'Image CFG Scale',\n    '#slMaskBlur sp-label': 'Mask blur',\n    '#slMaskExpansion sp-label': 'Mask Expansion',\n    '#slInpaintingMaskWeight .title': 'Inpainting conditioning mask strength',\n    '#slInpainting_fill .title': 'Masked content',\n    '#slInpainting_fill [value=0]': 'fill',\n    '#slInpainting_fill [value=1]': 'original',\n    '#slInpainting_fill [value=2]': 'latent noise',\n    '#slInpainting_fill [value=3]': 'latent nothing',\n    '#chInpaintFullRes': 'Inpaint at Full Res',\n    '#chRestoreFaces': 'Restore Faces',\n    '#chHiResFixs': 'Highres. fix',\n    '#HiResDiv .title': 'Upscaler',\n    '#HiResStep': 'Hires steps',\n    '#hrScaleSlider .title': 'Hires Scale',\n    '#hrDenoisingStrength .title': 'High Res Denoising Strength',\n    '#hrWidth': 'Hi Res Output Width',\n    '#hrHeight': 'Hi Res Output Height',\n    '#lNameInpaintPdding': 'Inpaint Padding',\n    '#btnRandomSeed': 'Random',\n    '#btnLastSeed': 'Last',\n    '#sampler_group sp-label': 'Sampling method',\n    '#sdLabelSeed': 'Seed',\n    '#collapsible': 'Show Samplers',\n    '#slHeight .title': 'Height',\n    '#slWidth .title': 'Width',\n    '#sdLabelSampleStep': 'Sampling Steps',\n}\n\nfunction renderLocale(locale: string) {\n    Object.keys(elemSelectorForLocale).forEach((selector) => {\n        const elem = document.querySelector(selector)\n        if (elem) {\n            // @ts-ignore\n            elem.innerHTML = Locale(elemSelectorForLocale[selector])\n        }\n    })\n}\n\nreaction(() => globalStore.Locale, renderLocale)\nrenderLocale(globalStore.Locale)\n"
  },
  {
    "path": "typescripts/locale/locale.ts",
    "content": "import globalStore from '../globalstore'\nimport type zhHans from '../../i18n/zh_CN/sd-official.json'\nimport type zhHansForPSPlugin from '../../i18n/zh_CN/ps-plugin.json'\nimport { lstatSync, readFileSync } from 'fs'\n\nconst localeFileCache: any = {}\n\nfunction isExists(path: string): boolean {\n    try {\n        lstatSync(path)\n        // console.log(path, 'exists')\n        return true\n    } catch (e) {\n        // console.log(path, 'not exists')\n        return false\n    }\n}\n\nexport default function Locale(\n    key: keyof typeof zhHans | keyof typeof zhHansForPSPlugin | any\n): string {\n    const locale = globalStore.Locale\n\n    const sdOfficialJSONPath = `plugin:/i18n/${locale}/sd-official.json`\n    let sdOfficialTranslate = localeFileCache[sdOfficialJSONPath]\n    if (!localeFileCache[sdOfficialJSONPath] && isExists(sdOfficialJSONPath)) {\n        console.log('readFile')\n        sdOfficialTranslate = JSON.parse(\n            readFileSync(sdOfficialJSONPath, 'utf-8')\n        )\n        localeFileCache[sdOfficialJSONPath] = sdOfficialTranslate\n    }\n\n    const psPluginJSONPath = `plugin:/i18n/${locale}/ps-plugin.json`\n    let psPluginTranslate = localeFileCache[psPluginJSONPath]\n    if (!localeFileCache[psPluginJSONPath] && isExists(psPluginJSONPath)) {\n        console.log('readFile')\n        psPluginTranslate = JSON.parse(readFileSync(psPluginJSONPath, 'utf-8'))\n        localeFileCache[psPluginJSONPath] = psPluginTranslate\n    }\n\n    let res = ''\n    //@ts-ignore\n    if (sdOfficialTranslate && key in sdOfficialTranslate)\n        res = sdOfficialTranslate[key]\n    //@ts-ignore\n    if (psPluginTranslate && key in psPluginTranslate)\n        res = psPluginTranslate[key]\n\n    res = res || key\n    return res\n}\n"
  },
  {
    "path": "typescripts/main/astore.ts",
    "content": "import { makeAutoObservable, reaction, toJS } from 'mobx'\nexport { toJS } from 'mobx'\n// import { Provider, inject, observer } from 'mobx-react'\ninterface AStoreData {\n    [key: string]: any\n}\nexport class AStore<T extends AStoreData> {\n    data: T\n\n    constructor(data: T) {\n        this.data = data\n\n        makeAutoObservable(this)\n    }\n\n    updateProperty(key: keyof T, value: any) {\n        this.data[key] = value\n    }\n    updatePropertyArray(key: keyof T, value: any) {\n        this.data[key] = this.data[key].concat(value)\n    }\n    updatePropertyArrayRemove(key: keyof T, valueToRemove: any) {\n        this.data[key] = this.data[key].filter(\n            (item: any) => item !== valueToRemove\n        )\n    }\n\n    toJsFunc() {\n        return toJS(this)\n    }\n}\n"
  },
  {
    "path": "typescripts/multiTextarea.tsx",
    "content": "import { observer } from 'mobx-react'\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { AStore } from './main/astore'\nimport { ErrorBoundary } from './util/errorBoundary'\nimport { Collapsible } from './util/collapsible'\nimport { autoResize } from './util/ts/general'\n\ninterface AStoreData {\n    positivePrompts: string[]\n    negativePrompts: string[]\n    current_index: number\n}\n\nconst defaultPositivePrompt = 'cute cat, {painterly_style_1}'\nconst defaultNegativePrompt = '{ugly}'\nexport const store = new AStore({\n    positivePrompts: [defaultPositivePrompt, ...Array(3).fill('')],\n    negativePrompts: [defaultNegativePrompt, ...Array(3).fill('')],\n\n    current_index: 0,\n})\nexport function getPrompt(): { positive: string; negative: string } {\n    const index: number = store.data.current_index\n    return {\n        positive: store.data.positivePrompts[index],\n        negative: store.data.negativePrompts[index],\n    }\n}\nexport function setPrompt({\n    positive,\n    negative,\n}: {\n    positive?: string\n    negative?: string\n}) {\n    const index: number = store.data.current_index\n    if (positive !== void 0 && positive !== null)\n        store.data.positivePrompts[index] = positive\n    if (negative !== void 0 && negative !== null)\n        store.data.negativePrompts[index] = negative\n}\n@observer\nexport class MultiTextArea extends React.Component {\n    componentDidMount(): void {\n        const taPrompt = document.querySelector('#taPrompt')\n\n        taPrompt?.addEventListener('focus', this.handleFocus)\n        taPrompt?.addEventListener('blur', this.handleBlur)\n    }\n    componentWillUnmount(): void {\n        const taPrompt = document.querySelector('#taPrompt')\n\n        taPrompt?.removeEventListener('focus', this.handleFocus)\n        taPrompt?.removeEventListener('blur', this.handleBlur)\n    }\n    handleFocus = () => {\n        // handle focus event here\n    }\n\n    handleBlur = () => {\n        // handle blur event here\n    }\n    switchTextArea(index: number) {\n        store.data.current_index = index\n        return store.data.current_index\n    }\n    handleInput(event: any) {\n        this.changePositivePrompt(event.target.value, store.data.current_index)\n    }\n    changePositivePrompt(text: string, index: number) {\n        try {\n            store.data.positivePrompts[index] = text\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    changeNegativePrompt(text: string, index: number) {\n        try {\n            // store.data.negativePrompt = text\n            store.data.negativePrompts[index] = text\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    render() {\n        return (\n            <div>\n                <sp-radio-group selected={store.data.current_index}>\n                    {store.data.positivePrompts.map(\n                        (text: string, index: number) => {\n                            return (\n                                <sp-radio\n                                    key={index}\n                                    onClick={() => {\n                                        try {\n                                            this.switchTextArea(index)\n\n                                            autoResize(\n                                                document.getElementById(\n                                                    'taPrompt'\n                                                ),\n                                                store.data.positivePrompts[\n                                                    store.data.current_index\n                                                ],\n                                                10\n                                            )\n\n                                            autoResize(\n                                                document.getElementById(\n                                                    'taNegativePrompt'\n                                                ),\n                                                store.data.negativePrompts[\n                                                    store.data.current_index\n                                                ],\n                                                10\n                                            )\n                                        } catch (e) {\n                                            console.warn(e)\n                                        }\n                                    }}\n                                    value={index}\n                                    checked={\n                                        store.data.current_index === index\n                                            ? true\n                                            : void 0\n                                    }\n                                >{`${index + 1}`}</sp-radio>\n                            )\n                        }\n                    )}\n                </sp-radio-group>\n                <sp-textarea\n                    id=\"taPrompt\"\n                    onInput={(event: any) => {\n                        try {\n                            this.changePositivePrompt(\n                                event.target.value,\n                                store.data.current_index\n                            )\n                            autoResize(\n                                event.target,\n                                store.data.positivePrompts[\n                                    store.data.current_index\n                                ]\n                            )\n                        } catch (e) {\n                            console.warn(e)\n                        }\n                    }}\n                    placeholder={`prompt ${store.data.current_index + 1}`}\n                    value={store.data.positivePrompts[store.data.current_index]}\n                ></sp-textarea>\n                <sp-textarea\n                    id=\"taNegativePrompt\"\n                    onInput={(event: any) => {\n                        try {\n                            this.changeNegativePrompt(\n                                event.target.value,\n                                store.data.current_index\n                            )\n\n                            autoResize(\n                                event.target,\n                                store.data.negativePrompts[\n                                    store.data.current_index\n                                ]\n                            )\n                        } catch (e) {\n                            console.warn(e)\n                        }\n                    }}\n                    placeholder={`negative prompt ${\n                        store.data.current_index + 1\n                    }`}\n                    value={store.data.negativePrompts[store.data.current_index]}\n                ></sp-textarea>\n            </div>\n        )\n    }\n}\n\n// const containers = document.querySelectorAll('.multiPromptsContainer')!\n\n// containers.forEach((container) => {\n//     const root = ReactDOM.createRoot(container)\n\n//     root.render(\n//         //<React.StrictMode>\n//             <ErrorBoundary>\n//                 <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n//                     <Collapsible defaultIsOpen={true} label={'Prompts'}>\n//                         <MultiTextArea />\n//                     </Collapsible>\n//                 </div>\n//             </ErrorBoundary>\n//         //</React.StrictMode>\n//     )\n// })\n"
  },
  {
    "path": "typescripts/one_button_prompt/one_button_prompt.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { Collapsible } from '../util/collapsible'\nimport { observer } from 'mobx-react'\nimport { AStore } from '../main/astore'\n\nimport { requestPost, requestGet, isScriptInstalled } from '../util/ts/api'\nimport {\n    ScriptInstallComponent,\n    SpMenu,\n    SpSliderWithLabel,\n} from '../util/elements'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { setPrompt } from '../multiTextarea'\nimport { autoResize } from '../util/ts/general'\n\ndeclare let g_sd_url: string\nexport const store = new AStore({\n    prompts: [] as string[],\n    number: 3,\n    prompt_complexity: 5,\n    subjects: [] as string[],\n    artists: [] as string[],\n    imagetypes: [] as string[],\n    subject: 'all',\n    artist: 'all',\n    imagetype: 'all',\n    script_name: 'one button prompt',\n    is_installed: false,\n})\n\nexport async function requestRandomPrompts(\n    number_of_prompts: number = 1,\n    insanitylevel: number = 5,\n    subject: string = 'all',\n    artist: string = 'all',\n    imagetype: string = 'all'\n) {\n    const payload = {\n        numberofprompts: number_of_prompts,\n        insanitylevel: insanitylevel,\n        forcesubject: subject,\n        artists: artist,\n        imagetype: imagetype,\n        onlyartists: false,\n        antivalues: '',\n        prefixprompt: '',\n        suffixprompt: '',\n        promptcompounderlevel: '1',\n        seperator: 'comma',\n        givensubject: '',\n        smartsubject: true,\n        giventypeofimage: '',\n        imagemodechance: 20,\n    }\n    try {\n        const full_url = `${g_sd_url}/one_button_prompt/prompt/random`\n\n        const randomPrompts = (await requestPost(full_url, payload))?.prompts\n        return randomPrompts\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nlet g_timeout: any\n\nfunction handleInput(event: any) {\n    try {\n        // clearTimeout(g_timeout)\n        // g_timeout = setTimeout(() => autoResize(event.target), 1000)\n        autoResize(event.target, event.target.value)\n    } catch (e) {\n        console.warn(e)\n    }\n}\nexport async function requestConfig() {\n    try {\n        const full_url = `${g_sd_url}/one_button_prompt/config`\n\n        const ui_config = await requestGet(full_url)\n\n        if (ui_config) {\n            store.data.subjects = ui_config?.subjects ?? []\n            store.data.artists = ui_config?.artists ?? []\n            store.data.imagetypes = ui_config?.imagetypes ?? []\n        }\n\n        return ui_config\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n@observer\nclass OneButtonPrompt extends React.Component {\n    async initScript() {\n        const is_installed = await isScriptInstalled(store.data.script_name)\n        await store.updateProperty('is_installed', is_installed)\n    }\n\n    async componentDidMount() {\n        await requestConfig()\n        await this.initScript()\n    }\n\n    renderContainer() {\n        return (\n            <div>\n                <div>\n                    <SpSliderWithLabel\n                        show-value={false}\n                        steps={1}\n                        out_min={1}\n                        out_max={10}\n                        output_value={store.data.prompt_complexity}\n                        title={`Higher levels increases complexity and randomness of generated\n                            prompt`}\n                        label={`Prompt Complexity`}\n                        onSliderInput={(output_value: number) => {\n                            store.data.prompt_complexity = output_value\n                        }}\n                    />\n                    <div>\n                        <SpMenu\n                            title=\"subjects\"\n                            items={store.data.subjects}\n                            label_item=\"Select a Subject\"\n                            selected_index={store.data.subjects.indexOf(\n                                store.data.subject\n                            )}\n                            onChange={(id: any, value: any) => {\n                                // console.log('onChange value: ', value)\n                                store.updateProperty('subject', value.item)\n                            }}\n                        ></SpMenu>\n                        <sp-label style={{ marginLeft: '3px' }}>\n                            Subject\n                        </sp-label>\n                    </div>\n                    <div>\n                        <SpMenu\n                            title=\"artists\"\n                            items={store.data.artists}\n                            label_item=\"Select an Artist\"\n                            selected_index={store.data.artists.indexOf(\n                                store.data.artist\n                            )}\n                            onChange={(id: any, value: any) => {\n                                // console.log('onChange value: ', value)\n                                store.updateProperty('artist', value.item)\n                            }}\n                        ></SpMenu>\n                        <sp-label style={{ marginLeft: '3px' }}>\n                            Artist\n                        </sp-label>\n                    </div>\n                    <div>\n                        <SpMenu\n                            title=\"image types\"\n                            items={store.data.imagetypes}\n                            label_item=\"Select an Image Type\"\n                            selected_index={store.data.imagetypes.indexOf(\n                                store.data.imagetype\n                            )}\n                            onChange={(id: any, value: any) => {\n                                // console.log('onChange value: ', value)\n                                store.updateProperty('imagetype', value.item)\n                            }}\n                        ></SpMenu>\n                        <sp-label style={{ marginLeft: '3px' }}>\n                            Image Type\n                        </sp-label>\n                    </div>\n                    <div\n                        style={{\n                            display: 'flex',\n                            justifyContent: 'space-between',\n                            width: '100%',\n                            marginTop: '5px',\n                        }}\n                    >\n                        <button\n                            style={{ float: 'right' }}\n                            className=\"btnSquare\"\n                            onClick={async () => {\n                                const prompt_complexity =\n                                    store.data.prompt_complexity ?? 5\n                                const subject = store.data.subject ?? 'all'\n                                const artist = store.data.artist ?? 'all'\n                                const imagetype = store.data.imagetype ?? 'all'\n                                store.data.prompts = await requestRandomPrompts(\n                                    3,\n                                    prompt_complexity,\n                                    subject,\n                                    artist,\n                                    imagetype\n                                )\n                            }}\n                        >\n                            Random Prompts\n                        </button>\n                    </div>\n                </div>\n                {store.data.prompts.map((prompt: string, index: number) => {\n                    return (\n                        <div\n                            key={`prompt-area-${index}`}\n                            style={{\n                                border: '2px solid #6d6c6c',\n                                padding: '3px',\n                            }}\n                        >\n                            <button\n                                className=\"btnSquare\"\n                                style={{ textAlign: 'right' }}\n                                onClick={() => {\n                                    //@ts-ignore\n                                    setPrompt({\n                                        positive: prompt,\n                                    })\n                                }}\n                            >\n                                use\n                            </button>\n                            <sp-textarea\n                                onInput={(event: any) => {\n                                    handleInput(event)\n                                    store.data.prompts[index] =\n                                        event.target.value\n                                }}\n                                placeholder={`random prompt ${index}`}\n                                value={prompt}\n                            ></sp-textarea>\n                        </div>\n                    )\n                })}\n            </div>\n        )\n    }\n\n    render() {\n        return (\n            <div>\n                {store.data.is_installed ? (\n                    <div style={{ padding: '4px' }}>\n                        {this.renderContainer()}\n                    </div>\n                ) : (\n                    <ScriptInstallComponent\n                        onRefreshHandler={async (event: any) => {\n                            console.log(`Refresh ${store.data.script_name}`)\n                            await requestConfig()\n                            await this.initScript()\n                        }}\n                    ></ScriptInstallComponent>\n                )}\n            </div>\n        )\n    }\n}\n\nconst containers = document.querySelectorAll('.oneButtonPromptContainer')!\n\ncontainers.forEach((container) => {\n    const root = ReactDOM.createRoot(container)\n\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible defaultIsOpen={false} label={'One Button Prompt'}>\n                    <OneButtonPrompt />\n                </Collapsible>\n            </div>\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n})\n"
  },
  {
    "path": "typescripts/preset/preset.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { observer } from 'mobx-react'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { Collapsible } from '../util/collapsible'\nimport Locale from '../locale/locale'\nimport { PresetTypeEnum } from '../util/ts/enum'\nimport {\n    getAllCustomPresetsSettings,\n    getCustomPresetsNames,\n    getLoadedPresets,\n    // getPresetType,\n    loadPresetSettingsFromFile,\n    preset_tab_store,\n    store,\n    updatePresetMenuEvent,\n    // updatePresetMenuEvent,\n} from './shared_ui_preset'\nimport { controlnet_preset, general, html_manip, io } from '../util/oldSystem'\nimport { AStore } from '../main/astore'\nimport { reaction, toJS } from 'mobx'\nimport { getUnitsData, setUnitData } from '../controlnet/entry'\nimport { SpMenu } from '../util/elements'\nimport { controlNetUnitData } from '../controlnet/store'\nimport { sd_tab_store } from '../stores'\nimport { storeToPreset, writePreset } from '../util/ts/io'\ndeclare let g_ui_settings_object: any\n\nreaction(\n    () => {\n        return preset_tab_store.data.new_preset\n    },\n    (current_preset: any) => {\n        try {\n            const text = JSON.stringify(current_preset, undefined, 7) || ''\n            const textarea_element = document.getElementById(\n                'taPresetSettings'\n            ) as any\n            textarea_element.value = text\n            updateTextAreaHeight(textarea_element)\n        } catch (e) {\n            console.error(e)\n        }\n    }\n)\n\nfunction getPresetSettingsHtml() {\n    //@ts-ignore\n    const value_str = document.getElementById('taPresetSettings')!.value\n    const value_json = JSON.parse(value_str)\n    return value_json\n}\n\nfunction updateTextAreaHeight(textarea_element: any) {\n    try {\n        //update the height of the text area to fit the settings in\n\n        const new_lines_count = general.countNewLines(textarea_element.value)\n        let height = new_lines_count * 12 + 100\n        height = Math.max(60, height)\n        height = Math.min(500, height)\n        textarea_element.style.height = height.toString() + 'px'\n    } catch (e) {\n        console.error(e)\n    }\n}\n\n// function setPresetName(preset_name: string) {\n//     //@ts-ignore\n//     document.getElementById('tiPresetName')!.value = preset_name\n// }\n\nasync function deletePreset() {\n    try {\n        const preset_file_name =\n            preset_tab_store.data.selected_preset_name + '.json'\n\n        const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(\n            'custom_preset'\n        )\n\n        await io.IOJson.deleteFile(custom_preset_entry, preset_file_name)\n        preset_tab_store.data.selected_preset_name = ''\n        preset_tab_store.data.new_preset = {}\n        store.data.custom_presets = await getAllCustomPresetsSettings()\n    } catch (e) {\n        console.error(e)\n    }\n}\nfunction filterControlnetUnitData(controlnet_units_data: controlNetUnitData[]) {\n    const filtered_data = controlnet_units_data.map((unit) => {\n        const {\n            input_image,\n            mask,\n            detect_map,\n            model_list,\n            module_list,\n            ...rest\n        } = unit\n        return rest\n    })\n    return filtered_data\n}\n\nexport function onNewPreset() {\n    const sd_tab_preset = storeToPreset(sd_tab_store)\n    const controlnet_tab_preset = toJS(getUnitsData())\n\n    const units = controlnet_tab_preset.map((unit: controlNetUnitData) => {\n        if (unit.enabled === false) return {}\n        else {\n            const {\n                input_image,\n                mask,\n                detect_map,\n                model_list,\n                module_list,\n                ...rest\n            } = unit\n            return rest\n        }\n    })\n\n    const plugin_preset = {\n        sd_tab_preset: sd_tab_preset,\n        controlnet_tab_preset: units,\n    }\n    preset_tab_store.data.new_preset = plugin_preset\n    return plugin_preset\n}\n\nasync function onSavePreset() {\n    if (preset_tab_store.data.new_preset_name) {\n        const preset_settings = getPresetSettingsHtml()\n        const preset_name = preset_tab_store.data.new_preset_name.trim()\n        const preset_file_name = preset_name + '.json' // will be used as file name\n        //check if the file exist and prompt the user to override it or cancel\n\n        const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(\n            'custom_preset'\n        )\n        await io.IOJson.saveJsonToFileExe(\n            preset_settings,\n            custom_preset_entry,\n            preset_file_name\n        )\n        store.data.custom_presets = await getAllCustomPresetsSettings()\n\n        console.log('store.data.custom_presets: ', store.data.custom_presets)\n        preset_tab_store.data.selected_preset_name = preset_name\n    }\n}\n\n@observer\nclass PresetTab extends React.Component<{}> {\n    async componentDidMount() {\n        // await populatePresetMenu()\n        try {\n            store.data.custom_presets = await getAllCustomPresetsSettings()\n\n            // store.data.controlnet_native_presets = {\n            //     ...controlnet_preset.ControlNetNativePresets,\n            // }\n        } catch (e) {\n            console.error(e)\n        }\n    }\n    renderTab() {\n        return (\n            <div>\n                <sp-textfield\n                    id=\"tiPresetName\"\n                    type=\"text\"\n                    placeholder=\"Preset Name\"\n                    value={preset_tab_store.data.new_preset_name}\n                    style={{ width: '160px' }}\n                    onInput={(event: any) => {\n                        preset_tab_store.data.new_preset_name =\n                            event.target.value\n                        // console.log(store.data.preset_name)\n                    }}\n                ></sp-textfield>\n                <button\n                    className=\"btnSquare\"\n                    id=\"btnGeneratePreset\"\n                    style={{ marginLeft: '5px' }}\n                    onClick={() => {\n                        onNewPreset()\n                    }}\n                >\n                    Generate Preset\n                </button>\n                <div style={{ marginTop: '3px' }}>\n                    <button\n                        className=\"btnSquare\"\n                        id=\"btnSavePreset\"\n                        style={{}}\n                        onClick={async () => {\n                            await onSavePreset()\n                        }}\n                    >\n                        Save Preset\n                    </button>\n                    <button\n                        className=\"btnSquare\"\n                        id=\"btnDeletePreset\"\n                        style={{ marginLeft: '5px' }}\n                        onClick={async () => {\n                            await deletePreset()\n                        }}\n                    >\n                        Delete Preset\n                    </button>\n                </div>\n                <div style={{ marginTop: '3px' }}>\n                    <SpMenu\n                        title=\"Custom Presets\"\n                        items={Object.keys(store.data.custom_presets)}\n                        label_item=\"Select a Custom Preset\"\n                        selected_index={Object.keys(\n                            store.data.custom_presets\n                        ).indexOf(preset_tab_store.data.selected_preset_name)}\n                        onChange={(id: any, value: any) => {\n                            // console.log('onChange value: ', value)\n                            // store.updateProperty('subject', value.item)\n                            console.log('value:', value)\n                            preset_tab_store.data.selected_preset_name =\n                                value.item\n                            preset_tab_store.data.new_preset_name = value.item\n                            preset_tab_store.data.new_preset =\n                                store.data.custom_presets[value.item]\n                        }}\n                    ></SpMenu>\n                </div>\n                <div>\n                    <sp-label id=\"lPresetName\">\n                        {preset_tab_store.data.new_preset_name.trim()}\n                    </sp-label>\n                </div>\n                <div>\n                    <sp-textarea\n                        id=\"taPresetSettings\"\n                        placeholder=\"{}\"\n                        value={\n                            JSON.stringify(\n                                preset_tab_store.data.new_preset,\n                                undefined,\n                                7\n                            ) || ''\n                        }\n                        onChange={(event: any) => {\n                            console.log('onChange:')\n                            updateTextAreaHeight(event.target)\n                        }}\n                        onInput={(event: any) => {\n                            console.log('onInput:')\n                            updateTextAreaHeight(event.target)\n                        }}\n                    ></sp-textarea>\n                </div>\n            </div>\n        )\n    }\n    render(): React.ReactNode {\n        return this.renderTab()\n    }\n}\n\nconst gridContainerNode = document.getElementById('PresetTabContainer')!\nconst gridRoot = ReactDOM.createRoot(gridContainerNode)\n\ngridRoot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n            <Collapsible defaultIsOpen={false} label={Locale('Custom Preset')}>\n                <PresetTab></PresetTab>\n            </Collapsible>\n        </div>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/preset/shared_ui_preset.ts",
    "content": "import { AStore } from '../main/astore'\nimport { html_manip, io } from '../util/oldSystem'\nimport { PresetTypeEnum } from '../util/ts/enum'\n// import { getNativeSDPresets } from '../util/ts/ui_ts'\n\nexport async function getLoadedPresets(ui_settings_obj: any) {\n    let customPresets\n\n    customPresets = await mapCustomPresetsToLoaders(ui_settings_obj)\n    console.log('customPresets: ', customPresets)\n    let loadedPresets = {\n        // ...getNativeSDPresets(),\n        ...customPresets,\n    }\n    return loadedPresets\n}\nexport const store = new AStore({\n    preset_name: '',\n    custom_presets: [] as any,\n    selected_preset_name: '',\n\n    sd_presets: [],\n    sd_native_presets: [],\n\n    selected_sd_preset_name: '', // the selected sd preset in sd tab\n    selected_sd_preset: {}, // the selected sd preset settings\n})\n\nexport const preset_tab_store = new AStore({\n    new_preset_name: '', //for the textfield field and label\n    new_preset: {} as any, // settings of the current preset tab preset\n    selected_preset_name: '', // name of the selected in the menu\n    selected_preset: {}, //settings of the selected preset in the menu\n})\nexport async function getCustomPresetEntries(preset_folder_name: string) {\n    const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(\n        preset_folder_name\n    )\n\n    const custom_preset_entries = await io.IOJson.getJsonEntries(\n        custom_preset_entry\n    )\n\n    return custom_preset_entries\n}\nexport async function loadPresetSettingsFromFile(preset_file_name: string) {\n    const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(\n        'custom_preset'\n    )\n    let preset_settings = {}\n    try {\n        preset_settings = await io.IOJson.loadJsonFromFile(\n            custom_preset_entry,\n            preset_file_name\n        )\n    } catch (e) {\n        console.warn(e)\n    }\n    return preset_settings\n}\n\nexport async function getAllCustomPresetsSettings() {\n    const custom_preset_entries = await getCustomPresetEntries('custom_preset')\n    let custom_presets: any = {}\n    for (const entry of custom_preset_entries) {\n        const preset_name: string = entry.name.split('.json')[0]\n        let preset_settings = await loadPresetSettingsFromFile(entry.name)\n\n        custom_presets[preset_name] = preset_settings\n    }\n    return custom_presets\n}\n\nconst updatePresetMenuEvent = new CustomEvent('updatePresetMenuEvent', {\n    detail: {},\n    bubbles: true,\n    cancelable: true,\n    composed: false,\n})\n\nexport function loadPreset(ui_settings: any, preset: any) {\n    console.log('preset:', preset)\n    ui_settings.autoFillInSettings(preset)\n}\nexport function loadCustomPreset(\n    ui_settings_obj: any,\n    custom_preset_settings: any\n) {\n    loadPreset(ui_settings_obj, custom_preset_settings)\n}\nexport async function mapCustomPresetsToLoaders(ui_settings_obj: any) {\n    const name_to_settings_obj = await getAllCustomPresetsSettings()\n    const preset_name_to_loader_obj: any = {}\n    for (const [preset_name, preset_settings] of Object.entries(\n        name_to_settings_obj\n    )) {\n        preset_name_to_loader_obj[preset_name] = () => {\n            loadCustomPreset(ui_settings_obj, preset_settings)\n        }\n    }\n    return preset_name_to_loader_obj\n}\n\nexport function getCustomPresetsNames(custom_presets: any) {\n    let presets_names: any = []\n    if (custom_presets) {\n        presets_names = Object.keys(custom_presets)\n    }\n    return presets_names\n}\n\nexport function onLoadControlnetPreset() {}\nexport function onLoadSDPreset() {}\n\n//sd preset = {preset_name: settings_json}\n//sd_preset_loader(sd_preset)\n\n//controlnet_preset = {preset_name: settings_json}\n\nexport { updatePresetMenuEvent }\n"
  },
  {
    "path": "typescripts/sam/sam.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { Collapsible } from '../util/collapsible'\nimport { observer } from 'mobx-react'\nimport { isScriptInstalled } from '../util/ts/api'\nimport { api, general, io, psapi, selection } from '../util/oldSystem'\nimport { Grid } from '../util/grid'\nimport { AStore } from '../main/astore'\nimport {\n    MoveToCanvasSvg,\n    PenSvg,\n    ScriptInstallComponent,\n} from '../util/elements'\nimport { selectionFromBlackAndWhiteImage } from '../util/ts/selection'\nimport { app } from 'photoshop'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport Locale from '../locale/locale'\n// import { settings_tab_ts } from '../entry'\nimport * as settings_tab_ts from '../settings/settings'\nimport { SelectionInfoType } from '../util/ts/enum'\ndeclare let g_sd_url: string\n\nexport async function getSamMap(base64: string, prompt: string) {\n    // const full_url = `${g_sd_url}/sam/dino-predict`\n    // const payload = {\n    //     dino_model_name: 'GroundingDINO_SwinT_OGC (694MB)',\n    //     input_image: base64,\n    //     text_prompt: 'the dog',\n    //     box_threshold: 0.3,\n    // }\n    const full_url = `${g_sd_url}/sam/sam-predict`\n\n    const payload = {\n        sam_model_name: 'sam_vit_h_4b8939.pth',\n        input_image: base64,\n        sam_positive_points: [],\n        sam_negative_points: [],\n        dino_enabled: true,\n        dino_model_name: 'GroundingDINO_SwinT_OGC (694MB)',\n        dino_text_prompt: prompt,\n        dino_box_threshold: 0.3,\n        dino_preview_checkbox: false,\n        dino_preview_boxes_selection: [0],\n    }\n    const result = await api.requestPost(full_url, payload)\n    return result\n}\nexport const store = new AStore({\n    thumbnails: [],\n    selection_info_list: [] as SelectionInfoType[],\n    prompt: '',\n    width: 85,\n    height: 85,\n    is_installed: false,\n    script_name: 'segment anything',\n})\n\n@observer\nexport class Sam extends React.Component<{\n    // store: AStore\n}> {\n    async initScript() {\n        const is_installed = await isScriptInstalled(store.data.script_name)\n        await store.updateProperty('is_installed', is_installed)\n    }\n    async componentDidMount(): Promise<void> {\n        await this.initScript()\n    }\n\n    renderScript() {\n        return (\n            <div>\n                <sp-textarea\n                    placeholder=\"Segment Anything Prompt\"\n                    value={store.data.prompt}\n                    onInput={(event: any) => {\n                        store.data.prompt = event.target.value\n                    }}\n                ></sp-textarea>\n                <button\n                    className=\"btnSquare\"\n                    onClick={async () => {\n                        const selection_info = await psapi.getSelectionInfoExe()\n                        const base64 = await io.getImageFromCanvas()\n                        const result = await getSamMap(\n                            base64,\n                            store.data.prompt\n                        )\n                        const masks = result?.masks ?? []\n                        const masks_urls = []\n                        for (const mask of masks) {\n                            const url =\n                                await io.convertBlackAndWhiteImageToRGBChannels3(\n                                    mask\n                                )\n                            masks_urls.push(url)\n                        }\n\n                        store.updateProperty('thumbnails', masks_urls)\n                        store.updateProperty(\n                            'selection_info_list',\n                            Array(masks_urls.length).fill(selection_info)\n                        )\n                    }}\n                >\n                    Generate Mask\n                </button>\n                <Grid\n                    // thumbnails_data={store.data.images?.map((base64: string) =>\n                    //     base64\n                    //         ? 'data:image/png;base64,' + base64\n                    //         : 'https://source.unsplash.com/random'\n                    // )}\n                    thumbnails={store.data.thumbnails}\n                    width={store.data.width}\n                    height={store.data.height}\n                    action_buttons={[\n                        {\n                            ComponentType: PenSvg,\n                            callback: async (index: number) => {\n                                try {\n                                    await psapi.unSelectMarqueeExe()\n                                    const base64 = general.base64UrlToBase64(\n                                        store.data.thumbnails[index]\n                                    )\n\n                                    await selectionFromBlackAndWhiteImage(\n                                        base64,\n                                        store.data.selection_info_list[index],\n                                        settings_tab_ts.store.data\n                                            .b_borders_or_corners\n                                    )\n\n                                    // try {\n                                    //     const base64 =\n                                    //         general.base64UrlToBase64(\n                                    //             store.data.thumbnails[index]\n                                    //         )\n                                    //     await selection.base64ToLassoSelection(\n                                    //         base64,\n                                    //         store.data.selection_info_list[\n                                    //             index\n                                    //         ]\n                                    //     )\n                                    // } catch (e) {\n                                    //     console.warn(e)\n                                    // }\n                                    //@ts-ignore\n                                    await eventHandler() // this will trigger the recalculation of the width and height sliders\n                                } catch (e) {\n                                    console.warn(e)\n                                }\n                            },\n                            title: Locale('Select Masked Area'),\n                        },\n                        {\n                            ComponentType: MoveToCanvasSvg,\n                            callback: async (index: number) => {\n                                try {\n                                    const to_x =\n                                        store.data.selection_info_list[index]\n                                            ?.left\n                                    const to_y =\n                                        store.data.selection_info_list[index]\n                                            ?.top\n                                    const width =\n                                        store.data.selection_info_list[index]\n                                            ?.width\n                                    const height =\n                                        store.data.selection_info_list[index]\n                                            ?.height\n\n                                    await io.IO.base64ToLayer(\n                                        general.base64UrlToBase64(\n                                            store.data.thumbnails[index]\n                                        ),\n                                        'segment_anything_mask.png',\n                                        to_x,\n                                        to_y,\n                                        width,\n                                        height\n                                    )\n                                } catch (e) {\n                                    console.warn(e)\n                                }\n                            },\n                            title: Locale('Copy Image to Canvas'),\n                        },\n                    ]}\n                ></Grid>\n            </div>\n        )\n    }\n    render() {\n        return (\n            <div>\n                {store.data.is_installed ? (\n                    this.renderScript()\n                ) : (\n                    <ScriptInstallComponent\n                        onRefreshHandler={async (event: any) => {\n                            console.log(`Refresh ${store.data.script_name}`)\n                            await this.initScript()\n                        }}\n                    ></ScriptInstallComponent>\n                )}\n            </div>\n        )\n    }\n}\nconst containers = document.querySelectorAll('.samContainer')\n\ncontainers.forEach((container) => {\n    const root = ReactDOM.createRoot(container)\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible defaultIsOpen={false} label={'Segment Anything'}>\n                    <Sam></Sam>\n                </Collapsible>\n            </div>\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n})\n"
  },
  {
    "path": "typescripts/sd_tab/sd_tab.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { observer } from 'mobx-react'\n\nimport { GenerationModeEnum, ScriptMode } from '../util/ts/enum'\nimport { reaction } from 'mobx'\nimport {\n    SearchableMenu,\n    SpCheckBox,\n    SpMenu,\n    SpSlider,\n    SpTextfield,\n} from '../util/elements'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { Collapsible } from '../util/collapsible'\n\nimport {\n    store,\n    refreshModels,\n    updateClickEventHandler,\n    tempDisableElement,\n    refreshUI,\n    getLoraModelPrompt,\n    requestLoraModels,\n    mode_config,\n    onModeChange,\n    initInitMaskElement,\n    widthSliderOnChangeEventHandler,\n    initPlugin,\n    helper_store,\n    viewMaskExpansion,\n    scaleFromToLabel,\n    mask_content_config,\n    requestGetHiResUpscalers,\n    selection_mode_config,\n    onWidthSliderInput,\n    onHeightSliderInput,\n    heightSliderOnChangeEventHandler,\n    loadPresetSettings,\n    isHiResMode,\n    comfy_mask_content_config,\n} from './util'\nimport { general } from '../util/oldSystem'\nimport { requestSwapModel, setInpaintMaskWeight } from '../util/ts/sdapi'\nimport { GenerateButtons } from '../session/generate'\nimport { MultiTextArea } from '../multiTextarea'\nimport { store as progress_store } from '../session/progress'\nimport { store as session_store } from '../session/session_store'\nimport { multiPrompts, settings_tab_ts } from '../entry'\nimport { getExpandedMask } from '../session/session'\nimport { mapRange } from '../controlnet/util'\n\nimport { store as preset_store } from '../preset/shared_ui_preset'\nimport Locale from '../locale/locale'\n\ndeclare let g_version: string\n\nreaction(\n    () =>\n        [store.data.is_lasso_mode, store.data.mode] as [\n            boolean,\n            GenerationModeEnum\n        ],\n    ([is_lasso_mode, mode]: [boolean, GenerationModeEnum]) => {\n        if (is_lasso_mode && mode === GenerationModeEnum.Inpaint) {\n            store.data.mode = GenerationModeEnum.LassoInpaint\n        } else if (!is_lasso_mode && mode === GenerationModeEnum.LassoInpaint) {\n            store.data.mode = GenerationModeEnum.Inpaint\n        }\n        // if (is_lasso_mode && mode === GenerationModeEnum.Outpaint) {\n        //     store.data.mode = GenerationModeEnum.LassoOutpaint\n        // } else if (\n        //     !is_lasso_mode &&\n        //     mode === GenerationModeEnum.LassoOutpaint\n        // ) {\n        //     store.data.mode = GenerationModeEnum.Outpaint\n        // }\n        console.log('store.data.is_lasso_mode:', store.data.is_lasso_mode)\n        console.log('store.data.mode:', store.data.mode)\n    }\n)\n\nconst handleLassoModeChange = (event: any) => {\n    store.updateProperty('is_lasso_mode', event.target.checked)\n}\nconst Modes = observer(() => {\n    const renderLassoModeElement = () => {\n        if (\n            [\n                GenerationModeEnum.Inpaint,\n                // GenerationModeEnum.Outpaint,\n                GenerationModeEnum.LassoInpaint,\n                // GenerationModeEnum.LassoOutpaint,\n            ].includes(store.data.mode)\n        ) {\n            return (\n                <>\n                    <div>\n                        <SpCheckBox\n                            // style={{ marginRight: '10px' }}\n                            onChange={handleLassoModeChange}\n                            checked={store.data.is_lasso_mode}\n                            // id={`chEnableControlNet_${this.props.index}`}\n                        >\n                            Lasso Mode\n                        </SpCheckBox>\n                        <SpCheckBox\n                            style={{\n                                marginLeft: '10px',\n                                display: store.data.is_lasso_mode\n                                    ? void 0\n                                    : 'none',\n                            }}\n                            onChange={() => {\n                                helper_store.data.make_square =\n                                    !helper_store.data.make_square\n                            }}\n                            checked={helper_store.data.make_square}\n                            // id={`chEnableControlNet_${this.props.index}`}\n                        >\n                            Make Square\n                        </SpCheckBox>\n\n                        <SpSlider\n                            show-value=\"false\"\n                            id=\"lasso_offset\"\n                            min=\"0\"\n                            max=\"100\"\n                            value={helper_store.data.lasso_offset}\n                            onInput={(evt: any) => {\n                                helper_store.data.lasso_offset = Number(\n                                    evt.target.value\n                                )\n                            }}\n                            style={{\n                                display: store.data.is_lasso_mode\n                                    ? void 0\n                                    : 'none',\n                            }}\n                        >\n                            <sp-label slot=\"label\" class=\"title\">\n                                Lasso Offset:\n                            </sp-label>\n                            <sp-label slot=\"label\">\n                                {helper_store.data.lasso_offset}\n                            </sp-label>\n                        </SpSlider>\n                    </div>\n                </>\n\n                // <sp-checkbox checked={store.data.is_lasso_mode ? true : void 0}>\n                //     lasso mode\n                // </sp-checkbox>\n            )\n        }\n    }\n    return <div>{renderLassoModeElement()}</div>\n})\n\n// const container = document.getElementById('reactModesContainer')!\n// const root = ReactDOM.createRoot(container)\n\n// root.render(\n//     //<React.StrictMode>\n//         <ErrorBoundary>\n//             <Modes />\n//         </ErrorBoundary>\n//     //</React.StrictMode>\n// )\n@observer\nclass SDTab extends React.Component<{}> {\n    async componentDidMount() {\n        try {\n            await refreshUI()\n            await initPlugin()\n\n            initInitMaskElement()\n            const btnSquareClass = document.getElementsByClassName('btnSquare')\n            //REFACTOR: move to events.js\n            for (let btnSquareButton of btnSquareClass) {\n                btnSquareButton.addEventListener('click', async (evt) => {\n                    // document.activeElement.blur()\n                    setTimeout(() => {\n                        try {\n                            //@ts-ignore\n                            evt.target.blur()\n                        } catch (e) {\n                            console.warn(e)\n                        }\n                    }, 500)\n                })\n            }\n\n            // html_manip.sliderAddEventListener_new(\n            //     'slImageCfgScale',\n            //     'lImageCfgScale',\n            //     0,\n            //     30,\n            //     0,\n            //     3\n            // )\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    render() {\n        const styles = {\n            menuBarContainer: {\n                // display: 'flex',\n            },\n            spMenu: {\n                // flex: 1,\n                width: '199px',\n                marginRight: '3px',\n            },\n            button: {\n                marginLeft: '3px',\n                // flex: 0.5,\n            },\n        }\n        return (\n            <div>\n                <div\n                    id=\"menu-bar-container\"\n                    style={{\n                        ...styles.menuBarContainer,\n                        width: '100%',\n                        display: 'flex',\n                        justifyContent: 'space-between',\n                    }}\n                >\n                    {/* <SpMenu\n                        title=\"Stable Diffusion Models\"\n                        items={helper_store.data.models || []}\n                        label_item=\"Select a Model\"\n                        style={{ ...styles.spMenu }}\n                        selected_index={(\n                            helper_store.data.models || []\n                        ).indexOf(store.data.selected_model)}\n                        onChange={(id: any, value: any) => {\n                            // console.log('onChange value: ', value)\n                            // store.updateProperty('subject', value.item)\n                            console.log('value:', value)\n                            store.data.selected_model = value.item\n\n                            requestSwapModel(store.data.selected_model)\n                        }}\n                    ></SpMenu> */}\n                    <SearchableMenu\n                        allItems={helper_store.data.models}\n                        placeholder={'Select a Model'}\n                        selected_item={store.data.selected_model}\n                        onSelectItemFailure={() => {\n                            const default_value =\n                                helper_store.data.models[0] || ''\n                            store.data.selected_model = default_value\n                            return default_value\n                        }}\n                        onChange={(item: any) => {\n                            store.data.selected_model = item\n\n                            requestSwapModel(store.data.selected_model)\n                        }}\n                    />\n\n                    <div style={{ display: 'flex', alignItems: 'flex-start' }}>\n                        <button\n                            style={{ padding: '3px' }}\n                            title=\"Refresh the plugin, only fixes minor issues.\"\n                            id=\"btnRefreshModels\"\n                            // style={styles.button}\n                            onClick={async (e) => {\n                                await refreshUI(true)\n\n                                tempDisableElement(e.target, 3000)\n                            }}\n                        >\n                            Refresh\n                        </button>\n                        <button\n                            style={{ padding: '3px' }}\n                            title=\"Update the plugin if you encounter bugs. Get the latest features\"\n                            className=\"btnSquare\"\n                            id=\"btnUpdate\"\n                            // style={styles.button}\n                            onClick={async () => {\n                                await updateClickEventHandler(g_version)\n                            }}\n                        >\n                            Update\n                        </button>\n                    </div>\n                </div>\n                <div id=\"sdBtnContainer\">\n                    {/* <SpMenu\n                        title=\"use lora in your prompt\"\n                        style={{ ...styles.spMenu }}\n                        // items={helper_store.data.loras.map((lora: any) => {\n                        //     return lora.name\n                        // })}\n                        items={helper_store.data.loras}\n                        label_item=\"Select Lora\"\n                        // selected_index={store.data.models\n                        //     .map((model) => {\n                        //         return model.title\n                        //     })\n                        //     .indexOf(store.data.selected_model)}\n                        onChange={(id: any, value: any) => {\n                            const lora_prompt = getLoraModelPrompt(value.item)\n                            const prompt = multiPrompts.getPrompt().positive\n                            multiPrompts.setPrompt({\n                                positive: `${prompt} ${lora_prompt}`,\n                            })\n                        }}\n                    ></SpMenu> */}\n                    <SearchableMenu\n                        allItems={helper_store.data.loras}\n                        placeholder={'Select Lora'}\n                        onChange={(item: any) => {\n                            const lora_prompt = getLoraModelPrompt(item)\n                            const prompt = multiPrompts.getPrompt().positive\n                            multiPrompts.setPrompt({\n                                positive: `${prompt} ${lora_prompt}`,\n                            })\n                        }}\n                    />\n                    {/* <SpMenu\n                        title=\"use textual inversion in your prompt\"\n                        style={{ ...styles.spMenu }}\n                        items={helper_store.data.embeddings}\n                        label_item=\"Select Textual Inversion\"\n                        onChange={(id: any, value: any) => {\n                            const prompt = multiPrompts.getPrompt().positive\n                            multiPrompts.setPrompt({\n                                positive: `${prompt} ${value.item}`,\n                            })\n                        }}\n                    ></SpMenu> */}\n                    <SearchableMenu\n                        allItems={helper_store.data.embeddings || []}\n                        placeholder={Locale('Select Textual Inversion')}\n                        onChange={(item: any) => {\n                            const prompt = multiPrompts.getPrompt().positive\n                            multiPrompts.setPrompt({\n                                positive: `${prompt} ${item}`,\n                            })\n                        }}\n                    />\n\n                    <sp-checkbox\n                        title=\"use {keyword} form the prompts library\"\n                        id=\"chUsePromptShortcut\"\n                        checked={\n                            settings_tab_ts.store.data.use_prompt_shortcut\n                                ? true\n                                : void 0\n                        }\n                        style={{ display: 'none' }}\n                        onClick={(\n                            event: React.ChangeEvent<HTMLInputElement>\n                        ) => {\n                            settings_tab_ts.store.data.use_prompt_shortcut =\n                                event.target.checked\n                        }}\n                    >\n                        prompt shortcut\n                    </sp-checkbox>\n                </div>\n                <div>\n                    <div id=\"progressContainer\">\n                        <div style={{ display: 'flex' }}>\n                            <sp-progressbar\n                                class=\"pProgressBars\"\n                                id=\"pProgressBar\"\n                                max=\"100\"\n                                value=\"0\"\n                                style={{ width: '120px' }}\n                            >\n                                <sp-label slot=\"label\" class=\"lProgressLabel\">\n                                    Progress...\n                                </sp-label>\n                            </sp-progressbar>\n                            <input\n                                title=\"Toggle the visibility of the Preview Image on the canvas\"\n                                type=\"checkbox\"\n                                name=\"optionCheckbox\"\n                                checked={\n                                    progress_store.data.live_progress_image\n                                }\n                                onChange={(evt) => {\n                                    progress_store.data.live_progress_image =\n                                        evt.target.checked\n                                }}\n                            />\n                        </div>\n                    </div>\n                    <GenerateButtons></GenerateButtons>\n\n                    <div\n                        style={{\n                            border: '2px solid #6d6c6c',\n                            padding: '3px',\n                        }}\n                    >\n                        <Collapsible\n                            defaultIsOpen={true}\n                            label={Locale('Prompts')}\n                        >\n                            <MultiTextArea />\n                        </Collapsible>\n                    </div>\n\n                    <sp-radio-group>\n                        {mode_config.map((config: any, index: number) => {\n                            return (\n                                <sp-radio\n                                    key={index}\n                                    title={config.title}\n                                    value={config.name}\n                                    id={config.id ?? void 0}\n                                    onClick={async (evt: any) => {\n                                        await onModeChange(evt.target.value)\n                                    }}\n                                    checked={\n                                        store.data.rb_mode === config.name\n                                            ? true\n                                            : void 0\n                                    }\n                                >\n                                    {Locale(config.name)}\n                                </sp-radio>\n                            )\n                        })}\n                    </sp-radio-group>\n                    <Modes />\n                    <div id=\"image_viewer\">\n                        <div className=\"imgButton\"></div>\n\n                        <table id=\"tableInitImageContainer\">\n                            <tbody>\n                                <tr>\n                                    <td id=\"initImageColumn\">\n                                        <div\n                                            id=\"init_image_container\"\n                                            className=\"imgContainer\"\n                                            style={{\n                                                display: [\n                                                    ScriptMode.Img2Img,\n                                                    ScriptMode.Inpaint,\n                                                    ScriptMode.Outpaint,\n                                                ].includes(store.data.rb_mode)\n                                                    ? void 0\n                                                    : 'none',\n                                            }}\n                                        >\n                                            <div>\n                                                <img\n                                                    id=\"init_image\"\n                                                    className=\"column-item-image\"\n                                                    src=\"https://source.unsplash.com/random\"\n                                                    width=\"300px\"\n                                                    height=\"100px\"\n                                                />\n                                            </div>\n                                            <div className=\"imgButton\">\n                                                <button\n                                                    className=\"column-item button-style disabled-btn\"\n                                                    disabled\n                                                    id=\"bSetInitImage\"\n                                                >\n                                                    Image\n                                                </button>\n                                            </div>\n                                        </div>\n                                    </td>\n                                    <td>\n                                        <div\n                                            id=\"init_image_mask_container\"\n                                            className=\"imgContainer\"\n                                            style={{\n                                                display: [\n                                                    ScriptMode.Inpaint,\n                                                    ScriptMode.Outpaint,\n                                                ].includes(store.data.rb_mode)\n                                                    ? void 0\n                                                    : 'none',\n                                            }}\n                                        >\n                                            <div>\n                                                <img\n                                                    id=\"init_image_mask\"\n                                                    className=\"column-item-image\"\n                                                    src=\"https://source.unsplash.com/random\"\n                                                    width=\"100px\"\n                                                    height=\"100px\"\n                                                />\n                                            </div>\n                                            <div className=\"imgButton\">\n                                                <button\n                                                    className=\"column-item button-style disabled-btn\"\n                                                    disabled\n                                                    id=\"bSetInitImageMask\"\n                                                >\n                                                    Mask\n                                                </button>\n                                            </div>\n                                        </div>\n                                    </td>\n                                </tr>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n                <div>\n                    <div id=\"batchNumberUi\">\n                        <div\n                            style={{\n                                width: '100%',\n                                display: 'flex',\n                                justifyContent: 'space-around',\n                            }}\n                        >\n                            <div\n                                id=\"batchNumberSdUiTabContainer\"\n                                style={{\n                                    width: '35%',\n                                    display: 'flex',\n                                    flexDirection: 'column',\n                                    alignItems: 'flex-start',\n                                }}\n                            >\n                                <sp-label>{Locale('Batch Size:')}</sp-label>\n                                <SpTextfield\n                                    style={{ width: '100%' }}\n                                    title=\"the number of images to generate at once.The larger the number more VRAM stable diffusion will use.\"\n                                    id=\"tiNumberOfBatchSize\"\n                                    type=\"number\"\n                                    placeholder=\"1\"\n                                    value={store.data.batch_size.toFixed(0)}\n                                    onChange={(evt: any) => {\n                                        let value = parseInt(evt.target.value)\n                                        if (!isFinite(value) || value < 1)\n                                            value = 1\n                                        // evt.target.value = value\n                                        store.data.batch_size = value\n                                    }}\n                                ></SpTextfield>\n                            </div>\n                            <div\n                                id=\"batchCountSdUiTabContainer\"\n                                style={{\n                                    width: '20%',\n                                    display: 'flex',\n                                    flexDirection: 'column',\n                                    alignItems: 'flex-start',\n                                }}\n                            >\n                                <sp-label>{Locale('Batch Count:')}</sp-label>\n                                <SpTextfield\n                                    style={{ width: '100%' }}\n                                    title=\"the number of images to generate in queue. The larger the number the longer will take.\"\n                                    id=\"tiNumberOfBatchCount\"\n                                    type=\"number\"\n                                    placeholder=\"1\"\n                                    value={store.data.batch_count}\n                                    onChange={(evt: any) => {\n                                        store.data.batch_count = parseInt(\n                                            evt.target.value\n                                        )\n                                    }}\n                                ></SpTextfield>\n                            </div>\n                            <div\n                                style={{\n                                    width: '35%',\n                                    display: 'flex',\n                                    flexDirection: 'column',\n                                    alignItems: 'flex-start',\n                                }}\n                            >\n                                <sp-label id=\"sdLabelSampleStep\">\n                                    {Locale('Sampling Steps:')}\n                                </sp-label>\n                                <SpTextfield\n                                    style={{ width: '100%' }}\n                                    title=\"the higher the steps the longer it will take to generate an image\"\n                                    id=\"tiNumberOfSteps\"\n                                    type=\"number\"\n                                    placeholder=\"20\"\n                                    value={store.data.steps.toFixed(0)}\n                                    onChange={(evt: any) => {\n                                        let value = evt.target.value\n                                        store.data.steps = parseInt(value)\n                                    }}\n                                ></SpTextfield>\n                            </div>\n                        </div>\n                    </div>\n                    <div id=\"selectionMode\">\n                        <div>\n                            <sp-label id=\"rbSelectionModeLabel\" slot=\"label\">\n                                {Locale('Selection Mode:')}\n                            </sp-label>\n                        </div>\n\n                        <div\n                            id=\"menu-bar-container_preset\"\n                            style={{ display: 'inline-flex' }}\n                        >\n                            <sp-radio-group id=\"selectionModeGroup\" class=\"\">\n                                {selection_mode_config.map(\n                                    (selection_mode, index) => {\n                                        return (\n                                            <sp-radio\n                                                key={index}\n                                                class=\"rbSelectionMode\"\n                                                checked={\n                                                    store.data\n                                                        .selection_mode ===\n                                                    selection_mode.value\n                                                        ? true\n                                                        : void 0\n                                                }\n                                                value={selection_mode.value}\n                                                title={selection_mode.title}\n                                                onClick={async (evt: any) => {\n                                                    store.data.selection_mode =\n                                                        selection_mode.value\n                                                    try {\n                                                        const selectionInfo =\n                                                            //@ts-ignore\n                                                            await psapi.getSelectionInfoExe()\n                                                        //@ts-ignore\n                                                        await calcWidthHeightFromSelection(\n                                                            selectionInfo\n                                                        )\n                                                    } catch (e) {\n                                                        console.warn(e)\n                                                    }\n                                                }}\n                                            >\n                                                {Locale(selection_mode.name)}\n                                            </sp-radio>\n                                        )\n                                    }\n                                )}\n                            </sp-radio-group>\n\n                            <div id=\"sdPresetContainer\">\n                                <SpMenu\n                                    size=\"s\"\n                                    title=\"Custom Presets\"\n                                    items={Object.keys({\n                                        ...helper_store.data.native_presets,\n                                        ...preset_store.data.custom_presets,\n                                    })}\n                                    label_item=\"Select a Custom Preset\"\n                                    selected_index={Object.keys({\n                                        ...helper_store.data.native_presets,\n                                        ...preset_store.data.custom_presets,\n                                    }).indexOf(\n                                        preset_store.data\n                                            .selected_sd_preset_name\n                                    )}\n                                    onChange={(id: any, value: any) => {\n                                        console.log('value:', value)\n                                        preset_store.data.selected_sd_preset_name =\n                                            value.item\n                                        preset_store.data.selected_sd_preset = {\n                                            ...helper_store.data.native_presets,\n                                            ...preset_store.data.custom_presets,\n                                        }[value.item]\n                                        console.log(\n                                            'preset_store.data.selected_sd_preset:',\n                                            preset_store.data.selected_sd_preset\n                                        )\n                                        loadPresetSettings(\n                                            preset_store.data.selected_sd_preset\n                                        )\n                                    }}\n                                ></SpMenu>\n                                {/* <sp-picker\n                                    title=\"auto fill the plugin with smart settings, to speed up your working process.\"\n                                    size=\"s\"\n                                    label=\"Smart Preset\"\n                                >\n                                    <sp-menu\n                                        id=\"mPresetMenu\"\n                                        slot=\"options\"\n                                    ></sp-menu>\n                                </sp-picker> */}\n                            </div>\n                        </div>\n                        <div>\n                            <sp-radio-group\n                                id=\"baseSizeGroup\"\n                                class=\"\"\n                                style={{\n                                    display:\n                                        store.data.selection_mode !== 'ratio'\n                                            ? 'hidden'\n                                            : undefined,\n                                }}\n                            >\n                                {[512, 768, 1024].map(\n                                    (base_size: number, index) => {\n                                        return (\n                                            <sp-radio\n                                                key={index}\n                                                class=\"rbBaseSize\"\n                                                checked={\n                                                    helper_store.data\n                                                        .base_size === base_size\n                                                        ? true\n                                                        : void 0\n                                                }\n                                                value={base_size}\n                                                title={base_size}\n                                                onClick={async (evt: any) => {\n                                                    helper_store.data.base_size =\n                                                        base_size\n\n                                                    try {\n                                                        const selectionInfo =\n                                                            //@ts-ignore\n                                                            await psapi.getSelectionInfoExe()\n                                                        //@ts-ignore\n                                                        await calcWidthHeightFromSelection(\n                                                            selectionInfo\n                                                        )\n                                                    } catch (e) {\n                                                        console.warn(e)\n                                                    }\n                                                }}\n                                            >\n                                                {base_size}\n                                            </sp-radio>\n                                        )\n                                    }\n                                )}\n                            </sp-radio-group>\n                        </div>\n                        <div\n                            style={{\n                                display: 'flex',\n                                justifyContent: 'center',\n                                alignItems: 'center',\n                            }}\n                        >\n                            <SpSlider\n                                show-value=\"false\"\n                                id=\"slWidth\"\n                                min=\"1\"\n                                max=\"256\"\n                                value={store.data.width / 8}\n                                // data-old_value=\"512\"\n                                onInput={(evt: any) => {\n                                    onWidthSliderInput(evt.target.value * 8)\n                                }}\n                                onChange={(evt: any) => {\n                                    store.data.width\n                                    widthSliderOnChangeEventHandler(\n                                        evt.target.value * 8,\n                                        8,\n                                        2048\n                                    )\n                                    helper_store.data.previous_width =\n                                        store.data.width\n                                }}\n                            >\n                                <sp-label slot=\"label\" class=\"title\">\n                                    {Locale('Width:')}\n                                </sp-label>\n                                <sp-label\n                                    class=\"labelNumber\"\n                                    slot=\"label\"\n                                    id=\"lWidth\"\n                                >\n                                    {parseInt(store.data.width as any)}\n                                </sp-label>\n                            </SpSlider>\n                            <button\n                                className=\"btnSquare linkSlider whiteChain\"\n                                id=\"linkWidthHeight\"\n                                title=\"maintain the ratio between width and height slider\"\n                                onClick={(evt: any) => {\n                                    evt.target.classList.toggle('blackChain')\n                                    const b_state =\n                                        !evt.target.classList.contains(\n                                            'blackChain'\n                                        ) //if doesn't has blackChain means => it's white => b_state == true\n                                    store.data.b_width_height_link = b_state\n                                }}\n                            ></button>\n                            <SpSlider\n                                show-value=\"false\"\n                                id=\"slHeight\"\n                                min=\"1\"\n                                max=\"256\"\n                                value={store.data.height / 8}\n                                onInput={async (evt: any) => {\n                                    onHeightSliderInput(evt.target.value * 8)\n                                }}\n                                onChange={(evt: any) => {\n                                    heightSliderOnChangeEventHandler(\n                                        evt.target.value * 8,\n                                        8,\n                                        2048\n                                    )\n                                }}\n                            >\n                                <sp-label slot=\"label\" class=\"title\">\n                                    {Locale('Height:')}\n                                </sp-label>\n                                <sp-label\n                                    class=\"labelNumber\"\n                                    slot=\"label\"\n                                    id=\"lHeight\"\n                                >\n                                    {parseInt(store.data.height as any)}\n                                </sp-label>\n\n                                <sp-label\n                                    class={\n                                        'res-increase ' +\n                                        (store.data.ratio < 1\n                                            ? 'res-decrease'\n                                            : void 0)\n                                    }\n                                    id=\"res-difference\"\n                                    slot=\"label\"\n                                >\n                                    {store.data.ratio < 1 ? '↓' : '↑'}\n                                    {'x'}\n                                    {(store.data.ratio < 1\n                                        ? 1 / store.data.ratio\n                                        : store.data.ratio\n                                    ).toFixed(2)}\n                                </sp-label>\n                            </SpSlider>\n                        </div>\n\n                        <div style={{ display: 'flex' }}>\n                            <SpSlider\n                                title=\"larger value will put more emphasis on the prompt\"\n                                show-value=\"true\"\n                                id=\"slCfgScale\"\n                                min=\"1\"\n                                max=\"30\"\n                                value={store.data.cfg}\n                                onInput={(evt: any) => {\n                                    store.data.cfg = evt.target.value\n                                }}\n                            >\n                                <sp-label slot=\"label\" class=\"title\">\n                                    {Locale('CFG Scale:')}\n                                </sp-label>\n                            </SpSlider>\n\n                            <SpSlider\n                                show-value=\"false\"\n                                id=\"slDenoisingStrength\"\n                                min=\"0\"\n                                max=\"100\"\n                                value={store.data.denoising_strength * 100}\n                                style={{\n                                    display: [\n                                        ScriptMode.Img2Img,\n                                        ScriptMode.Inpaint,\n                                        ScriptMode.Outpaint,\n                                    ].includes(store.data.rb_mode)\n                                        ? void 0\n                                        : 'none',\n                                }}\n                                onInput={(evt: any) => {\n                                    store.data.denoising_strength =\n                                        evt.target.value / 100\n                                }}\n                            >\n                                <sp-label slot=\"label\" class=\"title\">\n                                    {Locale('Denoising Strength:')}\n                                </sp-label>\n                                <sp-label slot=\"label\" id=\"lDenoisingStrength\">\n                                    {store.data.denoising_strength.toFixed(2)}\n                                </sp-label>\n                            </SpSlider>\n                        </div>\n                        <SpSlider\n                            title=\"Pix2Pix CFG Scale (larger value will put more emphasis on the image)\"\n                            show-value=\"false\"\n                            id=\"slImageCfgScale\"\n                            min=\"0\"\n                            max=\"30\"\n                            value={general.mapRange(\n                                store.data.image_cfg_scale,\n                                0,\n                                3,\n                                0,\n                                30\n                            )}\n                            style={{\n                                display:\n                                    [\n                                        ScriptMode.Img2Img,\n                                        ScriptMode.Inpaint,\n                                    ].includes(store.data.rb_mode) &&\n                                    settings_tab_ts.store.data\n                                        .use_image_cfg_scale_slider\n                                        ? void 0\n                                        : 'none',\n                            }}\n                            onInput={(evt: any) => {\n                                store.data.image_cfg_scale = general.mapRange(\n                                    evt.target.value,\n                                    0,\n                                    30,\n                                    0,\n                                    3\n                                )\n                            }}\n                        >\n                            <sp-label slot=\"label\" class=\"title\">\n                                Image CFG Scale:\n                            </sp-label>\n                            <sp-label slot=\"label\" id=\"lImageCfgScale\">\n                                {store.data.image_cfg_scale}\n                            </sp-label>\n                        </SpSlider>\n\n                        <SpSlider\n                            show-value=\"true\"\n                            id=\"slMaskBlur\"\n                            min=\"0\"\n                            max=\"64\"\n                            value={store.data.mask_blur}\n                            style={{\n                                display: [\n                                    ScriptMode.Inpaint,\n                                    ScriptMode.Outpaint,\n                                ].includes(store.data.rb_mode)\n                                    ? void 0\n                                    : 'none',\n                            }}\n                            disabled={\n                                settings_tab_ts.store.data.use_sharp_mask\n                                    ? true\n                                    : void 0\n                            }\n                            onChange={async (evt: any) => {\n                                const mask =\n                                    session_store.data.preprocessed_mask\n                                const iterations = store.data.mask_expansion\n                                const mask_blur = parseInt(evt.target.value)\n                                store.data.mask_blur = mask_blur\n                                session_store.data.expanded_mask =\n                                    await getExpandedMask(\n                                        mask,\n                                        iterations,\n                                        mask_blur\n                                    )\n                                if (session_store.data.expanded_mask) {\n                                    viewMaskExpansion()\n                                }\n                            }}\n                        >\n                            <sp-label slot=\"label\">Mask Blur:</sp-label>\n                        </SpSlider>\n                        <SpSlider\n                            show-value=\"true\"\n                            id=\"slMaskExpansion\"\n                            min=\"0\"\n                            max=\"256\"\n                            value={store.data.mask_expansion}\n                            title=\"the larger the value the more the mask will expand, '0' means use precise masking, use in combination with the mask blur\"\n                            style={{\n                                display: [\n                                    ScriptMode.Inpaint,\n                                    ScriptMode.Outpaint,\n                                ].includes(store.data.rb_mode)\n                                    ? void 0\n                                    : 'none',\n                            }}\n                            onChange={async (evt: any) => {\n                                const mask =\n                                    session_store.data.preprocessed_mask\n                                const iterations = parseInt(evt.target.value)\n                                store.data.mask_expansion = iterations\n                                const mask_blur = store.data.mask_blur\n                                session_store.data.expanded_mask =\n                                    await getExpandedMask(\n                                        mask,\n                                        iterations,\n                                        mask_blur\n                                    )\n                                if (session_store.data.expanded_mask) {\n                                    viewMaskExpansion()\n                                }\n                            }}\n                        >\n                            <sp-label slot=\"label\">\n                                {Locale('Mask Expansion:')}\n                            </sp-label>\n                        </SpSlider>\n\n                        <div style={{ display: 'flex' }}>\n                            <SpSlider\n                                show-value=\"false\"\n                                id=\"slInpaintingMaskWeight\"\n                                min=\"0\"\n                                max=\"100\"\n                                value={store.data.inpainting_mask_weight * 100}\n                                title=\"0 will keep the composition; 1 will allow composition to change\"\n                                style={{\n                                    display: [\n                                        ScriptMode.Img2Img,\n                                        ScriptMode.Inpaint,\n                                        ScriptMode.Outpaint,\n                                    ].includes(store.data.rb_mode)\n                                        ? void 0\n                                        : 'none',\n                                }}\n                                onInput={async (evt: any) => {\n                                    store.data.inpainting_mask_weight =\n                                        evt.target.value / 100\n                                }}\n                                onChange={async (evt: any) => {\n                                    try {\n                                        store.data.inpainting_mask_weight =\n                                            evt.target.value / 100\n\n                                        await setInpaintMaskWeight(\n                                            store.data.inpainting_mask_weight\n                                        )\n                                    } catch (e) {\n                                        console.warn(e)\n                                    }\n                                }}\n                            >\n                                <sp-label slot=\"label\" class=\"title\">\n                                    Inpainting conditioning mask strength:\n                                </sp-label>\n                                <sp-label\n                                    slot=\"label\"\n                                    id=\"lInpaintingMaskWeight\"\n                                >\n                                    {store.data.inpainting_mask_weight}\n                                </sp-label>\n                            </SpSlider>\n                        </div>\n\n                        <div\n                            id=\"slInpainting_fill\"\n                            style={{\n                                display: [\n                                    ScriptMode.Inpaint,\n                                    ScriptMode.Outpaint,\n                                ].includes(store.data.rb_mode)\n                                    ? void 0\n                                    : 'none',\n                            }}\n                        >\n                            <sp-radio-group id=\"Inpainting_fill_group\" class=\"\">\n                                <sp-label class=\"title\" slot=\"label\">\n                                    Mask Content:\n                                </sp-label>\n                                {(settings_tab_ts.store.data\n                                    .selected_backend === 'Automatic1111'\n                                    ? mask_content_config\n                                    : comfy_mask_content_config\n                                ).map((mask_content, index: number) => {\n                                    return (\n                                        <sp-radio\n                                            key={index}\n                                            class=\"rbMaskContent\"\n                                            checked={\n                                                store.data.inpainting_fill ===\n                                                mask_content.value\n                                                    ? true\n                                                    : void 0\n                                            }\n                                            value={mask_content.value}\n                                            onClick={(evt: any) => {\n                                                store.data.inpainting_fill =\n                                                    mask_content.value\n                                            }}\n                                        >\n                                            {Locale(`${mask_content.name}`)}\n                                        </sp-radio>\n                                    )\n                                })}\n                            </sp-radio-group>\n                        </div>\n\n                        <div style={{ display: 'flex' }}>\n                            <SpCheckBox\n                                class=\"checkbox\"\n                                id=\"chInpaintFullRes\"\n                                style={{\n                                    display: [\n                                        ScriptMode.Inpaint,\n                                        ScriptMode.Outpaint,\n                                    ].includes(store.data.rb_mode)\n                                        ? 'inline-flex' //void 0\n                                        : 'none',\n                                }}\n                                checked={store.data.inpaint_full_res}\n                                onClick={(evt: any) => {\n                                    store.data.inpaint_full_res =\n                                        evt.target.checked\n                                }}\n                            >\n                                Inpaint at Full Res\n                            </SpCheckBox>\n                            <SpCheckBox\n                                class=\"checkbox\"\n                                id=\"chRestoreFaces\"\n                                checked={store.data.restore_faces}\n                                onClick={(evt: any) => {\n                                    store.data.restore_faces =\n                                        evt.target.checked\n                                }}\n                            >\n                                {Locale('Restore Faces')}\n                            </SpCheckBox>\n                            <SpCheckBox\n                                class=\"checkbox\"\n                                id=\"chHiResFixs\"\n                                style={{\n                                    display: isHiResMode() ? 'flex' : 'none',\n                                }}\n                                checked={store.data.enable_hr}\n                                onClick={(evt: any) => {\n                                    store.data.enable_hr = evt.target.checked\n                                }}\n                            >\n                                {Locale('Hi Res Fix')}\n                            </SpCheckBox>\n                            <SpCheckBox\n                                class=\"checkbox\"\n                                id=\"\"\n                                checked={store.data.tiling}\n                                onClick={(evt: any) => {\n                                    store.data.tiling = evt.target.checked\n                                }}\n                            >\n                                {Locale('Tiling')}\n                            </SpCheckBox>\n                        </div>\n                        <div\n                            id=\"HiResDiv\"\n                            style={{\n                                display:\n                                    isHiResMode() && store.data.enable_hr\n                                        ? void 0\n                                        : 'none',\n                            }}\n                        >\n                            <div style={{ display: 'flex' }}>\n                                <div>\n                                    <sp-label\n                                        id=\"lHiResUpscaler\"\n                                        style={{ marginBottom: '3px' }}\n                                    >\n                                        Upscaler:\n                                    </sp-label>\n                                    <SpMenu\n                                        title=\"select an upscaler model\"\n                                        items={\n                                            helper_store.data.hr_upscaler_list\n                                        }\n                                        label_item=\"Select an Upscaler\"\n                                        selected_index={helper_store.data.hr_upscaler_list.indexOf(\n                                            store.data.hr_upscaler\n                                        )}\n                                        onChange={(id: any, value: any) => {\n                                            store.data.hr_upscaler = value.item\n                                        }}\n                                    ></SpMenu>\n                                </div>\n                                <div>\n                                    <sp-label id=\"HiResStep\">\n                                        Hi Res Steps:\n                                    </sp-label>\n                                    <SpTextfield\n                                        id=\"hrNumberOfSteps\"\n                                        type=\"number\"\n                                        placeholder=\"0\"\n                                        value={store.data.hr_second_pass_steps}\n                                        style={{\n                                            marginTop: '3px',\n                                            width: 'auto',\n                                        }}\n                                        onChange={(evt: any) => {\n                                            store.data.hr_second_pass_steps =\n                                                parseInt(evt.target.value)\n                                        }}\n                                    ></SpTextfield>\n                                </div>\n                            </div>\n                            <div\n                                id=\"hi-res-sliders-container\"\n                                style={{ display: 'flex' }}\n                            >\n                                <SpSlider\n                                    show-value=\"false\"\n                                    id=\"hrScaleSlider\"\n                                    min=\"1\"\n                                    max=\"100\"\n                                    value=\"50\"\n                                    onInput={(evt: any) => {\n                                        store.data.hr_scale = mapRange(\n                                            evt.target.value,\n                                            1,\n                                            100,\n                                            1,\n                                            4,\n                                            0.1\n                                        )\n                                    }}\n                                >\n                                    <sp-label slot=\"label\" class=\"title\">\n                                        Hi Res Scale:\n                                    </sp-label>\n                                    <sp-label\n                                        class=\"labelNumber\"\n                                        slot=\"label\"\n                                        id=\"hrScaleLabel\"\n                                    >\n                                        {store.data.hr_scale.toFixed(2)}\n                                    </sp-label>\n                                    <sp-label\n                                        class=\"labelNumber\"\n                                        slot=\"label\"\n                                        id=\"lHrScaleFromTo\"\n                                    >\n                                        {scaleFromToLabel(\n                                            store.data.width,\n                                            store.data.height,\n                                            store.data.hr_scale\n                                        )}\n                                    </sp-label>\n                                </SpSlider>\n                                <SpSlider\n                                    show-value=\"false\"\n                                    id=\"hrDenoisingStrength\"\n                                    min=\"0\"\n                                    max=\"100\"\n                                    value={mapRange(\n                                        store.data.hr_denoising_strength,\n                                        0,\n                                        1,\n                                        0,\n                                        100,\n                                        1\n                                    ).toFixed(2)}\n                                    onInput={(evt: any) => {\n                                        store.data.hr_denoising_strength =\n                                            mapRange(\n                                                evt.target.value,\n                                                0,\n                                                100,\n                                                0,\n                                                1,\n                                                0.01\n                                            )\n                                    }}\n                                >\n                                    <sp-label slot=\"label\" class=\"title\">\n                                        High Res Denoising Strength:\n                                    </sp-label>\n                                    <sp-label\n                                        slot=\"label\"\n                                        id=\"hDenoisingStrength\"\n                                    >\n                                        {store.data.hr_denoising_strength.toFixed(\n                                            2\n                                        )}\n                                    </sp-label>\n                                </SpSlider>\n\n                                <SpSlider\n                                    show-value=\"false\"\n                                    id=\"hrWidth\"\n                                    min=\"1\"\n                                    max=\"256\"\n                                    value={store.data.hr_resize_x / 8}\n                                    style={{ display: 'none' }}\n                                    onInput={(evt: any) => {\n                                        store.data.hr_resize_x = Math.floor(\n                                            evt.target.value * 8\n                                        )\n                                    }}\n                                >\n                                    <sp-label slot=\"label\" class=\"title\">\n                                        Hi Res Output Width:\n                                    </sp-label>\n                                    <sp-label\n                                        class=\"labelNumber\"\n                                        slot=\"label\"\n                                        id=\"hWidth\"\n                                    >\n                                        {store.data.hr_resize_x}\n                                    </sp-label>\n                                </SpSlider>\n\n                                <SpSlider\n                                    show-value=\"false\"\n                                    id=\"hrHeight\"\n                                    min=\"1\"\n                                    max=\"256\"\n                                    value={store.data.hr_resize_y / 8}\n                                    style={{ display: 'none' }}\n                                    onInput={(evt: any) => {\n                                        store.data.hr_resize_y = Math.floor(\n                                            evt.target.value * 8\n                                        )\n                                    }}\n                                >\n                                    <sp-label slot=\"label\">\n                                        Hi Res Output Height:\n                                    </sp-label>\n                                    <sp-label\n                                        class=\"labelNumber\"\n                                        slot=\"label\"\n                                        id=\"hHeight\"\n                                    >\n                                        {store.data.hr_resize_y}\n                                    </sp-label>\n                                </SpSlider>\n                            </div>\n                        </div>\n                        <SpSlider\n                            show-value=\"false\"\n                            id=\"slInpaintPadding\"\n                            min=\"0\"\n                            max=\"64\"\n                            value={store.data.inpaint_full_res_padding}\n                            style={{\n                                display:\n                                    [\n                                        ScriptMode.Inpaint,\n                                        ScriptMode.Outpaint,\n                                    ].includes(store.data.rb_mode) &&\n                                    store.data.inpaint_full_res\n                                        ? void 0\n                                        : 'none',\n                            }}\n                            onInput={(evt: any) => {\n                                const padding = evt.target.value * 4\n                                store.data.inpaint_full_res_padding = padding\n                            }}\n                        >\n                            <sp-label slot=\"label\" id=\"lNameInpaintPdding\">\n                                Inpaint Padding:\n                            </sp-label>\n                            <sp-label\n                                class=\"labelNumber\"\n                                slot=\"label\"\n                                id=\"lInpaintPadding\"\n                            >\n                                {store.data.inpaint_full_res_padding}\n                            </sp-label>\n                        </SpSlider>\n                    </div>\n\n                    <div>\n                        <div style={{ display: 'flex' }}>\n                            <sp-label id=\"sdLabelSeed\">\n                                {Locale('Seed:')}\n                            </sp-label>\n                            <sp-textfield\n                                id=\"tiSeed\"\n                                placeholder=\"Seed\"\n                                value={store.data.seed}\n                                onInput={(evt: any) => {\n                                    store.data.seed = evt.target.value\n                                }}\n                            ></sp-textfield>\n                            <button\n                                className=\"btnSquare\"\n                                id=\"btnRandomSeed\"\n                                style={{\n                                    marginRight: '3px',\n                                    marginLeft: '3px',\n                                }}\n                                onClick={(evt: any) => {\n                                    store.data.seed = '-1'\n                                }}\n                            >\n                                {Locale('Random')}\n                            </button>\n                            <button\n                                className=\"btnSquare\"\n                                id=\"btnLastSeed\"\n                                onClick={() => {\n                                    store.data.seed =\n                                        session_store.data.last_seed\n                                }}\n                            >\n                                {Locale('Last')}\n                            </button>\n                        </div>\n                        <button\n                            type=\"button\"\n                            id=\"collapsible\"\n                            onClick={(evt: any) => {\n                                helper_store.data.b_show_sampler =\n                                    !helper_store.data.b_show_sampler\n                            }}\n                        >\n                            {helper_store.data.b_show_sampler ? 'Hide' : 'Show'}\n                            {' Samplers'} ({store.data.sampler_name})\n                        </button>\n                        <sp-radio-group\n                            id=\"sampler_group\"\n                            class=\"content\"\n                            selected={store.data.sampler_name}\n                            style={{\n                                display: helper_store.data.b_show_sampler\n                                    ? 'block'\n                                    : 'none',\n                            }}\n                        >\n                            <sp-label slot=\"label\">\n                                {Locale('Select Sampler:')}\n                            </sp-label>\n                            {(helper_store.data.sampler_list || []).map(\n                                (sampler: any, index: number) => {\n                                    return (\n                                        <sp-radio\n                                            class=\"rbSampler\"\n                                            checked={\n                                                sampler ===\n                                                store.data.sampler_name\n                                                    ? true\n                                                    : void 0\n                                            }\n                                            value={sampler}\n                                            key={index}\n                                            onClick={(evt: any) => {\n                                                store.data.sampler_name =\n                                                    sampler\n                                            }}\n                                        >\n                                            {sampler}\n                                        </sp-radio>\n                                    )\n                                }\n                            )}\n                        </sp-radio-group>\n                    </div>\n                </div>\n            </div>\n        )\n    }\n}\n\nconst sdTabContainer = document.getElementById('sdTabContainer')!\nconst sdTabRoot = ReactDOM.createRoot(sdTabContainer)\nsdTabRoot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        {/* <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible\n                    defaultIsOpen={true}\n                    label={Locale('Stable Diffusion Tab')}\n                >\n                    <SDTab></SDTab>\n                </Collapsible>\n            </div> */}\n        <SDTab></SDTab>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/sd_tab/util.ts",
    "content": "import { control_net } from '../entry'\nimport vae_settings from '../settings/vae'\nimport { AStore } from '../main/astore'\nimport { script_store } from '../ultimate_sd_upscaler/scripts'\nimport { ScriptMode } from '../ultimate_sd_upscaler/ultimate_sd_upscaler'\nimport {\n    dialog_box,\n    general,\n    html_manip,\n    sampler_data,\n    settings_tab,\n    thumbnail,\n} from '../util/oldSystem'\nimport { requestGet } from '../util/ts/api'\n\nimport { GenerationModeEnum, SelectionInfoType } from '../util/ts/enum'\nimport {\n    getVersionRequest,\n    requestGetModels,\n    requestGetSamplers,\n    requestGetUpscalers,\n    setInpaintMaskWeight,\n} from '../util/ts/sdapi'\nimport { store as session_store } from '../session/session_store'\nimport settings_tab_ts from '../settings/settings'\nimport { setUnitData } from '../controlnet/entry'\nimport { controlNetUnitData } from '../controlnet/store'\nimport { presetToStore } from '../util/ts/io'\nimport { refreshExtraUpscalers } from '../extra_page/extra_page'\n\nimport { readdirSync, readFileSync } from 'fs'\nimport comfyapi from '../comfyui/comfyapi'\ndeclare let g_models: any[]\ndeclare let g_automatic_status: any\ndeclare let g_sd_options_obj: any\n\ndeclare let g_controlnet_max_models: number\ndeclare let g_sd_url: string\n\nexport const mode_config = [\n    {\n        name: 'txt2img',\n        title: 'use this mode to generate images from text only',\n        id: '',\n    },\n    {\n        name: 'img2img',\n        title: 'use this mode to generate variation of an image',\n        id: '',\n    },\n    {\n        name: 'inpaint',\n        title: 'use this mode to generate variation of a small area of an image, while keeping the rest of the image intact',\n        id: 'rbModeInpaint',\n    },\n    {\n        name: 'outpaint',\n        title: 'use this mode to (1) fill any missing area of an image,(2) expand an image',\n        id: '',\n    },\n]\nexport const mask_content_config = [\n    {\n        name: 'fill',\n        value: 0,\n    },\n    {\n        name: 'original',\n        value: 1,\n    },\n    {\n        name: 'latent noise',\n        value: 2,\n    },\n    {\n        name: 'latent nothing',\n        value: 3,\n    },\n]\nexport const comfy_mask_content_config = [\n    // {\n    //     name: 'fill',\n    //     value: 0,\n    // },\n    {\n        name: 'original',\n        value: 1,\n    },\n    // {\n    //     name: 'latent noise',\n    //     value: 2,\n    // },\n    {\n        name: 'latent nothing',\n        value: 3,\n    },\n]\nexport enum SelectionModeEnum {\n    Ratio = 'ratio',\n    Precise = 'precise',\n    Ignore = 'ignore',\n}\nexport const selection_mode_config = [\n    {\n        name: 'ratio',\n        value: 'ratio',\n        title: '',\n    },\n    {\n        name: 'precise',\n        value: 'precise',\n        title: 'use the selection area width and height to fill the width and height sliders',\n    },\n    {\n        name: 'ignore',\n        value: 'ignore',\n        title: 'fill the width and height sliders manually',\n    },\n]\n\nexport const store = new AStore({\n    selected_model: '',\n    is_lasso_mode: false,\n    mode: GenerationModeEnum.Txt2Img,\n    rb_mode: ScriptMode.Txt2Img,\n\n    batch_size: 1,\n    batch_count: 1,\n    steps: 20,\n    width: 512,\n    height: 512,\n    ratio: 1.0,\n    cfg: 7.0,\n    b_width_height_link: true,\n    denoising_strength: 0.7,\n    hr_denoising_strength: 0.5,\n    inpaint_full_res: false,\n    enable_hr: false,\n    sampler_name: 'Euler a',\n    image_cfg_scale: 1.5,\n    seed: '-1' as string,\n    mask_blur: 0,\n    mask_expansion: 0,\n    inpaint_full_res_padding: 0,\n\n    hr_scale: 2.0,\n\n    hr_resize_x: 512,\n    hr_resize_y: 512,\n    hr_second_pass_steps: 20,\n    restore_faces: false,\n    // inpainting_fill: mask_content_config[0].value,\n    inpainting_fill: 1, //set original as default value\n\n    hr_upscaler: '',\n\n    selection_mode: selection_mode_config[0].value,\n    inpainting_mask_weight: 1,\n    tiling: false,\n})\nexport const default_preset = {\n    sd_tab_preset: {\n        prompt: '',\n        negative_prompt: '',\n        // is_lasso_mode: false,\n\n        batch_size: 1,\n        batch_count: 1,\n        steps: 20,\n        width: 512,\n        height: 512,\n        ratio: 1,\n        cfg: 7,\n        b_width_height_link: true,\n        denoising_strength: 0.7,\n        hr_denoising_strength: 0.7,\n        // inpaint_full_res: false,\n        // enable_hr: false,\n        sampler_name: 'Euler a',\n        image_cfg_scale: 1.5,\n        seed: '-1',\n        mask_blur: 0,\n        mask_expansion: 0,\n        inpaint_full_res_padding: 0,\n        hr_scale: 2,\n        hr_resize_x: 512,\n        hr_resize_y: 512,\n        hr_second_pass_steps: 0,\n        // restore_faces: false,\n        inpainting_fill: 1,\n        hr_upscaler: '',\n        selection_mode: 'ratio',\n    },\n    controlnet_tab_preset: [{}, {}, {}, {}, {}, {}, {}],\n}\n\nexport const helper_store = new AStore({\n    b_show_sampler: false, //false when off, true when on,\n    models: [] as any[],\n    loras: [] as any[],\n    embeddings: [] as any[],\n    sampler_list: [] as any[],\n    hr_upscaler_list: [] as string[],\n    previous_width: 512,\n    previous_height: 512,\n    native_presets: {},\n    base_size: 512 as number,\n    lasso_offset: 10 as number,\n    make_square: true as boolean,\n})\nexport async function refreshModels() {\n    let b_result = false\n    try {\n        g_models = await requestGetModels()\n        if (g_models.length > 0) {\n            b_result = true\n            helper_store.data.models = g_models\n                ? g_models.map((model) => {\n                      return model.title\n                  })\n                : helper_store.data.models\n        }\n\n        // for (let model of g_models) {\n        //     // console.log(model.title)//Log\n        //     // const menu_item_element = document.createElement('sp-menu-item')\n        //     // menu_item_element.className = 'mModelMenuItem'\n        //     menu_item_element.innerHTML = model.title\n        //     menu_item_element.dataset.model_hash = model.hash\n        //     menu_item_element.dataset.model_title = model.title\n        //     // document\n        //     //     .getElementById('mModelsMenu')\n        //     //     .appendChild(menu_item_element)\n        // }\n    } catch (e) {\n        b_result = false\n        console.warn(e)\n    }\n    return b_result\n}\n\nasync function promptForUpdate(header_message: any, long_message: any) {\n    const shell = require('uxp').shell\n\n    ;(async () => {\n        const buttons = ['Cancel', 'OK']\n        const r1 = await dialog_box.prompt(\n            header_message,\n            long_message,\n            buttons\n            // 'Please Update you Plugin. it will take about 10 seconds to update',\n            // 'update from discord, update from github'[\n            // ['Cancel', 'Discord', 'Github']\n            // ('Cancel', 'OK')\n            // ]\n        )\n        let url\n        try {\n            if (r1 === 'Cancel') {\n                /* cancelled or No */\n                console.log('cancel')\n            } else if (r1 === 'Github') {\n                url =\n                    'https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin'\n                // await py_re.openUrlRequest(url)\n            } else if (r1 === 'Discord') {\n                console.log('Discord')\n                // url = 'https://discord.gg/3mVEtrddXJ'\n                // url = 'https://discord.gg/YkUJXYWK3c'\n                // await py_re.openUrlRequest(url)\n            } else if (r1 === 'Ok') {\n            }\n            // console.log('url: ', url)\n        } catch (e) {\n            console.warn(e, url)\n        }\n    })()\n}\nexport async function updateClickEventHandler(current_version: string) {\n    try {\n        const online_data = await general.requestOnlineData()\n        const b_need_update = general.compareVersions(\n            current_version,\n            online_data.new_version\n        )\n\n        let header_message = 'Your Plugin is up to date.'\n        let long_message = ''\n        if (b_need_update) {\n            header_message = `New Version is Available (${online_data.new_version})`\n            long_message = online_data.update_message\n        }\n\n        await promptForUpdate(header_message, long_message)\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nexport function tempDisableElement(element: any, time: number) {\n    element.classList.add('disableBtn')\n    element.disabled = true\n    // element.style.opacity = '0.65'\n    // element.style.cursor = 'not-allowed'\n    setTimeout(function () {\n        element.disabled = false\n        element.classList.remove('disableBtn')\n        // element.style.opacity = '1.0'\n        // element.style.cursor = 'default'\n    }, time)\n}\n\nasync function updateVersionUI() {\n    let bStatus = false\n    try {\n        const version = await getVersionRequest()\n        document.getElementById('lVersionNumber')!.textContent = version\n        if (version !== 'v0.0.0') {\n            bStatus = true\n        }\n    } catch (e) {\n        console.warn(e)\n        document.getElementById('lVersionNumber')!.textContent = 'v0.0.0'\n        bStatus = false\n    }\n    return bStatus\n}\n\n//REFACTOR: move to generation_settings.js\nexport async function initSamplers() {\n    try {\n        let samplers = await requestGetSamplers()\n        if (samplers.length > 0) {\n            helper_store.data.sampler_list = samplers.map((sampler: any) => {\n                return sampler.name\n            })\n            store.data.sampler_name = helper_store.data.sampler_list[0]\n        }\n        return samplers\n    } catch (e) {\n        console.warn(e)\n    }\n    return []\n}\n\nexport function loadNativePreset() {\n    const json_container: { [key: string]: any } = {}\n    const dir = 'plugin:/presets' // specify the directory containing the .json files\n\n    readdirSync(dir).forEach((file) => {\n        if (file.endsWith('.json')) {\n            const fileContent = readFileSync(`${dir}/${file}`, 'utf8')\n            const fileNameWithoutExtension = file.slice(0, -5)\n            json_container[fileNameWithoutExtension] = JSON.parse(fileContent)\n        }\n    })\n\n    console.log(json_container)\n    return json_container\n}\nexport async function refreshUI(display_error = false) {\n    try {\n        const b_proxy_server_status = await updateVersionUI()\n        if (b_proxy_server_status) {\n            html_manip.setProxyServerStatus('connected', 'disconnected')\n            // g_automatic_status = Enum.AutomaticStatusEnum['RunningWithApi']\n        } else {\n            html_manip.setProxyServerStatus('disconnected', 'connected')\n        }\n\n        helper_store.data.native_presets = loadNativePreset()\n        if (settings_tab_ts.store.data.selected_backend === 'Automatic1111') {\n            //@ts-ignore\n            g_automatic_status = await checkAutoStatus() // check the webui status regardless if alert are turned on or off\n            if (!settings_tab_ts.store.data.bTurnOffServerStatusAlert) {\n                //@ts-ignore\n                await displayNotification(g_automatic_status) // only show alert if the alert are turn on\n            }\n            const bSamplersStatus = await initSamplers()\n            await refreshModels()\n            helper_store.data.loras = await requestLoraModels()\n            helper_store.data.embeddings = await requestEmbeddings()\n            await refreshExtraUpscalers()\n            await setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start\n            //get the latest options\n\n            await g_sd_options_obj.getOptions()\n            //get the selected model\n            store.data.selected_model = g_sd_options_obj.getCurrentModel()\n            //update the ui with that model title\n\n            // const current_model_hash =\n            //     html_manip.getModelHashByTitle(current_model_title)\n            // html_manip.autoFillInModel(current_model_hash)\n\n            //fetch the inpaint mask weight from sd webui and update the slider with it.\n            const inpainting_mask_weight =\n                await g_sd_options_obj.getInpaintingMaskWeight()\n            console.log('inpainting_mask_weight: ', inpainting_mask_weight)\n            html_manip.autoFillInInpaintMaskWeight(inpainting_mask_weight)\n            //init ControlNet Tab\n\n            helper_store.data.hr_upscaler_list =\n                await requestGetHiResUpscalers()\n\n            g_controlnet_max_models =\n                await control_net.requestControlNetMaxUnits()\n            await control_net.initializeControlNetTab(g_controlnet_max_models)\n            await vae_settings.populateVAE()\n        }\n\n        if (settings_tab_ts.store.data.selected_backend === 'ComfyUI') {\n            await comfyapi.comfy_api.init(display_error)\n\n            helper_store.data.models = comfyapi.comfy_api.getModels()\n            store.data.selected_model = helper_store.data.models?.[0]\n\n            helper_store.data.sampler_list =\n                comfyapi.comfy_api.getSamplerNames()\n            store.data.sampler_name = helper_store.data.sampler_list?.[0]\n\n            vae_settings.store.data.vae_model_list =\n                comfyapi.comfy_api.getVAEs()\n            vae_settings.store.data.current_vae =\n                vae_settings.store.data.vae_model_list?.[0]\n\n            helper_store.data.hr_upscaler_list =\n                comfyapi.comfy_api.getHiResUpscalers()\n            store.data.hr_upscaler = helper_store.data.hr_upscaler_list?.[0]\n\n            helper_store.data.loras = comfyapi.comfy_api\n                .getLoras()\n                .map((lora) => lora.split('.')[0]) //remove .safetensor from loraname\n\n            const controlnet_models =\n                //@ts-ignorets\n                comfyapi.comfy_api.object_info?.ControlNetLoader.input.required\n                    .control_net_name[0]\n            const preprocessor_list = //@ts-ignorets\n                comfyapi.comfy_api?.object_info?.ControlNetScript.input.required\n                    .preprocessor_name_1[0]\n            const preprocessor_detail =\n                //@ts-ignorets\n                comfyapi.comfy_api?.object_info?.GetConfig.input.optional\n                    .controlnet_config\n            control_net.initializeControlNetTabComfyUI(\n                3,\n                controlnet_models,\n                preprocessor_list,\n                preprocessor_detail\n            )\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nexport async function requestGetHiResUpscalers(): Promise<string[]> {\n    try {\n        const full_url = `${g_sd_url}/sdapi/v1/upscalers`\n        let upscalers = await requestGet(full_url)\n        return [\n            'Latent',\n            'Latent (antialiased)',\n            'Latent (bicubic)',\n            'Latent (bicubic antialiased)',\n            'Latent (nearest)',\n            'Latent (nearest-exact)',\n            ...upscalers.map((upscaler: any) => upscaler.name),\n        ]\n    } catch (e) {\n        console.warn('requestGetHiResUpscalers:', e)\n        return [\n            'Latent',\n            'Latent (antialiased)',\n            'Latent (bicubic)',\n            'Latent (bicubic antialiased)',\n            'Latent (nearest)',\n            'Latent (nearest-exact)',\n        ]\n    }\n}\n\nexport async function requestLoraModels() {\n    const full_url = `${g_sd_url}/sdapi/v1/loras`\n    let lora_models = (await requestGet(full_url)) ?? []\n    if (lora_models.length > 0) {\n        lora_models = lora_models.map((lora: any) => {\n            return lora.name\n        })\n    }\n    return lora_models\n}\n\nexport async function requestEmbeddings() {\n    try {\n        const full_url = `${g_sd_url}/sdapi/v1/embeddings`\n        let results = (await requestGet(full_url)) || {}\n        let embeddings = Object.keys(results?.loaded || {})\n        return embeddings\n    } catch (e) {\n        console.error(e)\n        return []\n    }\n}\n\nexport function getLoraModelPrompt(lora_model_name: string) {\n    return `<lora:${lora_model_name}:1>`\n}\n\nexport async function onModeChange(new_mode: ScriptMode) {\n    try {\n        script_store.setMode(new_mode)\n        store.data.rb_mode = new_mode\n        store.data.mode = store.data.rb_mode as unknown as GenerationModeEnum\n\n        //@ts-ignore\n        await postModeSelection() // do things after selection\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nexport function viewMaskExpansion() {\n    if (session_store.data.expanded_mask) {\n        const mask_src = general.base64ToBase64Url(\n            session_store.data.expanded_mask\n        )\n        html_manip.setInitImageMaskSrc(mask_src)\n    } else {\n        console.log(\n            'the mask has not been expanded, g_generation_session.base64maskExpansionImage is empty'\n        )\n    }\n}\nfunction viewDrawnMask() {\n    //this is the generated mask or user drawn mask, but it's not the mask after expansion\n    if (session_store.data.mask) {\n        const mask_src = general.base64ToBase64Url(session_store.data.mask)\n        html_manip.setInitImageMaskSrc(mask_src)\n    } else {\n        console.log('no mask is available')\n    }\n}\nexport function initInitMaskElement() {\n    //make init mask image use the thumbnail class with buttons\n    const mask_image_html = html_manip.getInitImageMaskElement()\n    const mask_parent_element = mask_image_html.parentElement\n\n    const thumbnail_container = thumbnail.Thumbnail.wrapImgInContainer(\n        mask_image_html,\n        'viewer-image-container'\n    )\n    mask_parent_element.appendChild(thumbnail_container)\n    thumbnail.Thumbnail.addSPButtonToContainer(\n        thumbnail_container,\n        'svg_sp_btn',\n        'view original mask',\n\n        viewDrawnMask,\n        null\n    )\n    thumbnail.Thumbnail.addSPButtonToContainer(\n        thumbnail_container,\n        'svg_sp_btn_expand',\n        'view modified mask',\n\n        viewMaskExpansion,\n        null\n    )\n    // populateLoraModelMenu() // no need for await\n}\n\nfunction scaleToRatio(\n    newValue1: number,\n    oldValue1: number,\n    newValue2: undefined, //get ignored\n    oldValue2: number,\n    maxValue: number,\n    minValue: number\n) {\n    const ratio = newValue1 / oldValue1\n    let finalNewValue2 = Math.max(\n        minValue,\n        Math.min(maxValue, oldValue2 * ratio)\n    )\n    let finalNewValue1 = newValue1\n    if (finalNewValue2 === maxValue || finalNewValue2 === minValue) {\n        finalNewValue1 = oldValue1 * (finalNewValue2 / oldValue2)\n    }\n    return [finalNewValue1, finalNewValue2]\n}\n\nexport function widthSliderOnChangeEventHandler(\n    new_value: number,\n    min_value: number,\n    max_value: number\n) {\n    try {\n        const b_link = store.data.b_width_height_link\n        let final_width = new_value\n        let final_height\n        if (b_link) {\n            ;[final_width, final_height] = scaleToRatio(\n                new_value,\n                helper_store.data.previous_width,\n                undefined,\n                store.data.height,\n                max_value,\n                min_value\n            )\n\n            store.data.width = final_width\n            store.data.height = final_height\n\n            helper_store.data.previous_width = store.data.width\n            helper_store.data.previous_height = store.data.height\n        }\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport function heightSliderOnChangeEventHandler(\n    new_value: number,\n    min_value: number,\n    max_value: number\n) {\n    try {\n        let new_height = new_value\n        const b_link = store.data.b_width_height_link\n        let final_height = new_height\n        let final_width\n        if (b_link) {\n            ;[final_height, final_width] = scaleToRatio(\n                new_height,\n                helper_store.data.previous_height,\n                undefined,\n                store.data.width,\n                max_value,\n                min_value\n            )\n\n            store.data.width = final_width\n            store.data.height = final_height\n\n            helper_store.data.previous_width = store.data.width\n            helper_store.data.previous_height = store.data.height\n        }\n    } catch (e) {\n        console.error(e)\n    }\n}\nexport function calcLinkedValue(new_value: number) {}\nexport async function initPlugin() {\n    try {\n        //*) load plugin settings\n        //*) load horde settings\n        //*)\n        //*) initialize the samplers\n        //*)\n        await settings_tab.loadSettings()\n        // await horde_native.HordeSettings.loadSettings()\n        const bSamplersStatus = await initSamplers() //initialize the sampler\n        await setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start\n        await refreshUI()\n\n        //@ts-ignore\n        await loadPromptShortcut()\n        //@ts-ignore\n        await refreshPromptMenu()\n    } catch (e) {\n        console.error(e)\n    }\n}\nexport function scaleFromToLabel(width: number, height: number, scale: number) {\n    const hr_width = Math.ceil(width * scale)\n    const hr_height = Math.ceil(height * scale)\n    return `${width}x${height} -> ${hr_width}x${hr_height}`\n}\n\nexport function onWidthSliderInput(new_value: number) {\n    try {\n        store.data.width = new_value\n\n        store.data.ratio = calcRatio(\n            new_value,\n            store.data.height,\n            session_store.data.current_selection_info\n        )\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport function onHeightSliderInput(new_value: number) {\n    try {\n        store.data.height = new_value\n        store.data.ratio = calcRatio(\n            store.data.width,\n            new_value,\n            session_store.data.current_selection_info\n        )\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport function calcRatio(\n    width: number,\n    height: number,\n    selectionInfo: SelectionInfoType | undefined\n) {\n    let ratio = 1\n\n    if (selectionInfo) {\n        ratio = (width * height) / (selectionInfo.width * selectionInfo.height)\n    }\n    return ratio\n}\n\nexport function loadPresetSettings(preset: any) {\n    if (preset?.sd_tab_preset) {\n        presetToStore(preset?.sd_tab_preset, store)\n    }\n    if (preset?.controlnet_tab_preset) {\n        preset?.controlnet_tab_preset.forEach(\n            (unit: controlNetUnitData, index: number) => {\n                try {\n                    unit.filter_keyword = 'none' // value of 'none' will display all models and modules\n\n                    setUnitData(unit, index)\n                } catch (e) {\n                    console.log('error at unit index: ', index)\n                    console.error(e)\n                }\n            }\n        )\n        // io_ts.presetToStore(preset?.controlnet_tab_preset, store)\n    }\n}\nexport function isHiResMode() {\n    let is_hi_res_mode = false\n    if (settings_tab_ts.store.data.selected_backend === 'Automatic1111') {\n        is_hi_res_mode = [ScriptMode.Txt2Img].includes(store.data.rb_mode)\n    } else if (settings_tab_ts.store.data.selected_backend === 'ComfyUI') {\n        is_hi_res_mode = [\n            ScriptMode.Txt2Img,\n            ScriptMode.Img2Img,\n            ScriptMode.Inpaint,\n            ScriptMode.Outpaint,\n        ].includes(store.data.rb_mode)\n    }\n    return is_hi_res_mode\n}\n\nexport default {\n    store: store,\n    helper_store: helper_store,\n}\n"
  },
  {
    "path": "typescripts/session/generate.tsx",
    "content": "import { app } from 'photoshop'\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { observer } from 'mobx-react'\n\n// import { sd_tab_ts, session_ts, viewer } from '../entry'\nimport { store as session_store } from '../session/session_store'\nimport { Session } from '../session/session'\n// import * as sd_tab_ts from '../sd_tab/sd_tab'\nimport { store as sd_tab_store } from '../sd_tab/util'\nimport * as viewer from '../viewer/viewer'\n\nimport './style/generate.css'\nimport { io, note, psapi, selection } from '../util/oldSystem'\nimport { GenerationModeEnum } from '../util/ts/enum'\nimport { initializeBackground } from '../util/ts/document'\nimport Locale from '../locale/locale'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport {\n    store as viewer_store,\n    mask_store as viewer_mask_store,\n    // init_store as viewer_init_store,\n} from '../viewer/viewer_util'\nimport { settings_tab_ts } from '../entry'\n\ndeclare let g_automatic_status: any\ndeclare let g_current_batch_index: number\n//example: take 'oI' in 'LassoInpaint' and replace it with 'o I' thus creating 'Lasso Inpaint'\nconst modeDisplayNames = Object.fromEntries(\n    Object.entries(GenerationModeEnum).map(([key, value]) => [\n        value,\n        key.replace(/([a-z])([A-Z])/g, '$1 $2'),\n    ])\n)\n\nexport const GenerateButtons = observer(() => {\n    return (\n        <div>\n            <button\n                id=\"btnNewGenerate\"\n                className=\"btnSquare generateButtonMargin generateColor\"\n                onClick={handleGenerateBatch}\n                style={{\n                    display: session_store.data.can_generate ? void 0 : 'none',\n                }}\n            >\n                {Locale(`Generate ${modeDisplayNames[sd_tab_store.data.mode]}`)}\n            </button>\n            {session_store.data.can_generate ? (\n                <button\n                    onClick={handleGenerateMoreBatch}\n                    disabled={\n                        session_store.data.can_generate_more ? void 0 : true\n                    }\n                    id=\"btnNewGenerateMore\"\n                    className={\n                        'btnSquare generateButtonMargin generateMoreColor' +\n                        (session_store.data.can_generate_more\n                            ? ''\n                            : 'disableBtn')\n                    }\n                    style={{\n                        display: session_store.data.can_generate_more\n                            ? 'inline-block'\n                            : 'none',\n                    }}\n                >\n                    Generate more\n                </button>\n            ) : (\n                void 0\n            )}\n            {!session_store.data.can_generate ? (\n                <button\n                    onClick={handleInterrupt}\n                    id=\"btnNewInterrupt\"\n                    className=\"btnSquare generateButtonMargin\"\n                >\n                    Interrupt\n                </button>\n            ) : (\n                void 0\n            )}\n        </div>\n    )\n})\n\nconst ToolbarGenerateButtons = observer(() => {\n    const button_style: any = {\n        width: '30px',\n        height: '30px',\n        marginBottom: '3px',\n    }\n    const generate_display = session_store.data.can_generate\n        ? 'inline-flex'\n        : 'none'\n    const generate_more_display =\n        session_store.data.can_generate && session_store.data.can_generate_more\n            ? 'inline-flex'\n            : 'none'\n    const interrupt_display = session_store.data.can_generate\n        ? 'none'\n        : 'inline-flex'\n    return (\n        <div>\n            <button\n                title={Locale('Generate')}\n                className=\"btnSquare generateColor\"\n                onClick={handleGenerate}\n                style={{ ...button_style, display: generate_display }}\n            >\n                G\n            </button>\n            <button\n                title={Locale('Generate More')}\n                onClick={handleGenerateMore}\n                className={'btnSquare generateMoreColor'}\n                style={{\n                    ...button_style,\n                    display: generate_more_display,\n                }}\n            >\n                M\n            </button>\n            <button\n                title={Locale('Interrupt')}\n                onClick={handleInterrupt}\n                className=\"btnSquare\"\n                style={{\n                    ...button_style,\n                    display: interrupt_display,\n                }}\n            >\n                I\n            </button>\n        </div>\n    )\n})\nconst canStartSession = async () => {\n    // check for automatic1111 connection: fail if false\n    // check for automatic1111 api: fail if false\n    // check for having a background layer: create if false\n    // check for artboard: fail if true\n    // check for selection: fail if false\n    let can_start_session = false\n    try {\n        const selection_info = await psapi.getSelectionInfoExe()\n\n        if (selection_info) {\n            Session.endSession()\n\n            can_start_session = true\n        } else {\n            can_start_session = await note.Notification.inactiveSelectionArea(\n                session_store.data.is_active,\n                'Reuse Selection'\n            )\n            if (can_start_session) {\n                //end current session and start a new one\n                Session.endSession()\n                await psapi.reSelectMarqueeExe(session_store.data.selectionInfo)\n            }\n        }\n\n        if (settings_tab_ts.store.data.selected_backend === 'Automatic1111') {   \n            //@ts-ignore\n            g_automatic_status = await checkAutoStatus()\n            //@ts-ignore\n            await displayNotification(g_automatic_status)\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n\n    return can_start_session\n}\n\nconst resetBatch = () => {\n    g_current_batch_index = -1\n    session_store.data.is_interrupted = false\n}\n\nconst handleGenerate = async () => {\n    //save the active layer:\n    const active_layer = app.activeDocument.activeLayers[0]\n    //save user input for later\n\n    //1) save selection as channel\n\n    await selection.selectionToChannel('mask')\n\n    await initializeBackground() //fix background if there is a need\n    console.log('mode: ', sd_tab_store.data.mode)\n    try {\n        if (!(await canStartSession())) {\n            return void 0\n        }\n        var { output_images, response_json, ui_settings } =\n            await Session.generate(sd_tab_store.data.mode)\n\n        if (session_store.data.is_interrupted) {\n            //reselect the layer that was selected before the generation start\n            await psapi.selectLayersExe([active_layer])\n            return void 0\n        }\n\n        const thumbnail_list = []\n        for (const base64 of output_images) {\n            const thumbnail = await io.createThumbnail(base64, 300)\n            thumbnail_list.push(thumbnail)\n        }\n\n        viewer_store.updateProperty('thumbnails', thumbnail_list)\n        viewer_store.updateProperty('images', output_images)\n        if (\n            [\n                GenerationModeEnum.Inpaint,\n                GenerationModeEnum.LassoInpaint,\n                GenerationModeEnum.Outpaint,\n            ].includes(session_store.data.mode)\n        ) {\n            viewer_mask_store.updateProperty(\n                'output_images_masks',\n                Array(output_images.length).fill(ui_settings['mask'])\n            )\n        }\n        console.log('session_store.toJsFunc(): ', session_store.toJsFunc())\n    } catch (e) {\n        console.error(e)\n        console.warn('output_images: ', output_images)\n        console.warn('response_json: ', response_json)\n        console.warn('ui_settings: ', ui_settings)\n    }\n}\n\nconst handleGenerateMore = async () => {\n    try {\n        //save the active layer:\n        const active_layer = app.activeDocument.activeLayers[0]\n\n        var { output_images, response_json, ui_settings } =\n            await Session.generateMore()\n\n        if (session_store.data.is_interrupted) {\n            await psapi.selectLayersExe([active_layer]) // reselect the layer that was active layer before the generation start\n            return void 0\n        }\n\n        const thumbnail_list = []\n        for (const base64 of output_images) {\n            const thumbnail = await io.createThumbnail(base64, 300)\n            thumbnail_list.push(thumbnail)\n        }\n        viewer_store.data.thumbnails = [\n            ...viewer_store.data.thumbnails,\n            ...thumbnail_list,\n        ]\n\n        viewer_store.data.images = [\n            ...viewer_store.data.images,\n            ...output_images,\n        ]\n\n        if (\n            [\n                GenerationModeEnum.Inpaint,\n                GenerationModeEnum.LassoInpaint,\n                GenerationModeEnum.Outpaint,\n            ].includes(session_store.data.mode)\n        ) {\n            const new_masks: string[] = Array(output_images.length).fill(\n                ui_settings['mask']\n            )\n            viewer_mask_store.data.output_images_masks = [\n                ...viewer_mask_store.data.output_images_masks,\n                ...new_masks,\n            ]\n            // viewer_mask_store.updatePropertyArray(\n            //     'output_images_masks',\n            //     Array(output_images.length).fill(\n            //         session_store.data.expanded_mask\n            //     )\n            // )\n        }\n        // viewer.store.updateProperty('images', output_images)\n        // console.log(\n        //     'session_store.toJsFunc(): ',\n        //     session_store.toJsFunc()\n        // )\n    } catch (e) {\n        console.error(e)\n        console.warn('output_images: ', output_images)\n        console.warn('response_json: ', response_json)\n    }\n}\n\nconst handleGenerateBatch = async () => {\n    try {\n        const numberOfBatchCount: number = Math.floor(\n            sd_tab_store.data.batch_count\n        )\n\n        await handleGenerate() //first generation is always use handleGenerate\n        for (\n            let i = 1;\n            i < numberOfBatchCount && !session_store.data.is_interrupted;\n            i++\n        ) {\n            // if (g_batch_count_interrupt_status === true) {\n            //     break\n            // }\n            // g_current_batch_index = i\n            await handleGenerateMore()\n        }\n        resetBatch()\n        // g_batch_count_interrupt_status = false // reset for next generation\n        // g_current_batch_index = 0 // reset curent_batch_number\n    } catch (e) {\n        console.error(e)\n    }\n}\nconst handleGenerateMoreBatch = async () => {\n    try {\n        const numberOfBatchCount: number = Math.floor(\n            sd_tab_store.data.batch_count\n        )\n\n        // await handleGenerateMore() //first generation is always use handleGenerate\n        for (\n            let i = 0;\n            i < numberOfBatchCount && !session_store.data.is_interrupted;\n            i++\n        ) {\n            // if (g_batch_count_interrupt_status === true) {\n            //     break\n            // }\n            // g_current_batch_index = i\n            await handleGenerateMore()\n        }\n\n        // g_batch_count_interrupt_status = false // reset for next generation\n        // g_current_batch_index = 0 // reset curent_batch_number\n        resetBatch()\n    } catch (e) {\n        console.error(e)\n    }\n}\nconst handleInterrupt = async () => {\n    try {\n        await Session.interrupt()\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nconst toolBarButtonsContainer = document.getElementById(\n    'toolbarGenerateButtonsContainer'\n)!\nconst toolBarButtonsContainerRoot = ReactDOM.createRoot(toolBarButtonsContainer)\ntoolBarButtonsContainerRoot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <ToolbarGenerateButtons></ToolbarGenerateButtons>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/session/modes.ts",
    "content": "// import { control_net, scripts, session_ts } from '../entry'\n// import * as session_ts from '../session/session'\nimport * as scripts from '../ultimate_sd_upscaler/scripts'\nimport * as control_net from '../controlnet/entry'\nimport { store as session_store } from '../session/session_store'\nimport sd_tab_util from '../sd_tab/util'\nimport settings_tab from '../settings/settings'\nimport comfyui_main_ui from '../comfyui/main_ui'\nimport {\n    html_manip,\n    io,\n    layer_util,\n    psapi,\n    python_replacement,\n    selection,\n    session,\n} from '../util/oldSystem'\n\nimport { core } from 'photoshop'\nimport {\n    getEnableControlNet,\n    getModuleDetail,\n    mapPluginSettingsToControlNet,\n} from '../controlnet/entry'\n\nimport { store as extra_page_store } from '../extra_page/extra_page'\nimport { requestPost } from '../util/ts/api'\nimport { comfyapi, settings_tab_ts } from '../entry'\nimport { newOutputImageName } from '../util/ts/general'\nconst executeAsModal = core.executeAsModal\n\ndeclare let g_inpaint_mask_layer: any\ndeclare let g_sd_url: any\ndeclare let g_controlnet_max_models: any\ndeclare let g_generation_session: any\n\ninterface SessionData {\n    init_image?: string\n    mask?: string\n    selectionInfo?: any\n}\ninterface ImageInfo {\n    path: string\n    base64: string\n    auto_metadata: Record<string, any>\n}\n\nasync function saveOutputImagesToDrive(\n    images_info: ImageInfo[],\n    settings: Record<string, any>\n) {\n    const base64OutputImages = []\n    let index = 0\n    for (const image_info of images_info) {\n        const path = image_info['path']\n        const base64_image = image_info['base64']\n        base64OutputImages[index] = base64_image\n        const [document_name, image_name] = path.split('/')\n        await io.saveFileInSubFolder(base64_image, document_name, image_name) //save the output image\n        const json_file_name = `${image_name.split('.')[0]}.json`\n        settings['auto_metadata'] = image_info?.auto_metadata\n\n        await io.saveJsonFileInSubFolder(\n            settings,\n            document_name,\n            json_file_name\n        ) //save the settings\n        index += 1\n    }\n    if (settings_tab_ts.store.data.selected_backend === 'Automatic1111') {\n        session_store.data.last_seed =\n            images_info?.length > 0 ? images_info[0]?.auto_metadata?.Seed : '-1'\n    }\n    return base64OutputImages\n}\nasync function saveOutputImagesToDriveComfy(\n    base64_images: string[],\n    settings: Record<string, any>\n) {\n    let index = 0\n    const document_name = settings['uniqueDocumentId']\n    delete settings['alwayson_scripts']\n    for (const base64 of base64_images) {\n        const image_name = newOutputImageName()\n        await io.saveFileInSubFolder(base64, document_name, image_name) //save the output image\n        const json_file_name = `${image_name.split('.')[0]}.json`\n\n        await io.saveJsonFileInSubFolder(\n            settings,\n            document_name,\n            json_file_name\n        ) //save the settings\n        index += 1\n    }\n}\nclass Mode {\n    constructor() {}\n\n    async initializeSession(): Promise<SessionData> {\n        return {}\n    }\n    static async generate(settings: any): Promise<{\n        output_images: any\n        response_json: any\n    }> {\n        return { output_images: [], response_json: null }\n    }\n    //return settings that would be used by the restApi\n    static async getSettings(session_data: any) {\n        const ui_settings = await session.getSettings(session_data)\n\n        return ui_settings\n    }\n    //take the output from restapi and formate it to a standard formate the plugin ui understand\n    static async processOutput(images_info: any, settings: any): Promise<any> {\n        const base64OutputImages = await saveOutputImagesToDrive(\n            images_info,\n            settings\n        )\n        return base64OutputImages\n    }\n    static async interrupt() {\n        //automatic1111\n        if (settings_tab.store.data.selected_backend === 'Automatic1111') {\n            return await this.requestInterrupt()\n        } else if (settings_tab.store.data.selected_backend === 'ComfyUI') {\n            await comfyapi.comfy_api.interrupt()\n            //comfy\n        }\n    }\n\n    static async requestInterrupt() {\n        const full_url = `${g_sd_url}/sdapi/v1/interrupt`\n        try {\n            console.log('requestInterrupt: ')\n            let request = await fetch(full_url, {\n                method: 'POST',\n                headers: {\n                    Accept: 'application/json',\n                    'Content-Type': 'application/json',\n                },\n            })\n\n            // console.log('interrupt request:', request)\n            let json = await request.json()\n            return json\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\n\nexport class Txt2ImgMode extends Mode {\n    // constructor() {\n    // }\n\n    static async initializeSession(): Promise<SessionData> {\n        const selectionInfo = await psapi.getSelectionInfoExe()\n\n        const init_image = ''\n        const mask = ''\n        return { selectionInfo, init_image, mask }\n    }\n\n    //return settings that would be used by the restApi\n    // static async getSettings() {\n    //     const ui_settings = await session.getSettings()\n\n    //     return ui_settings\n    // }\n\n    //@ts-ignore\n    static async requestTxt2Img(payload) {\n        try {\n            console.log('requestTxt2Img(): about to send a fetch request')\n\n            let json = await python_replacement.txt2ImgRequest(payload)\n            console.log('requestTxt2Img json:', json)\n\n            return json\n        } catch (e) {\n            console.warn(e)\n            return {}\n        }\n    }\n\n    //REFACTOR: reuse the same code for (requestControlNetTxt2Img,requestControlNetImg2Img)\n    static async requestControlNetTxt2Img(plugin_settings: any) {\n        console.log('requestControlNetTxt2Img: ')\n\n        const full_url = `${g_sd_url}/sdapi/v1/txt2img`\n\n        const control_net_settings = await mapPluginSettingsToControlNet(\n            plugin_settings\n        )\n        let control_networks = []\n        // let active_control_networks = 0\n        for (let index = 0; index < g_controlnet_max_models; index++) {\n            if (!getEnableControlNet(index)) {\n                control_networks[index] = false\n                continue\n            }\n            control_networks[index] = true\n\n            const is_inpaint_model: boolean =\n                control_net_settings['controlnet_units'][index][\n                    'module'\n                ].includes('inpaint')\n            if (\n                !control_net_settings['controlnet_units'][index][\n                    'input_image'\n                ] &&\n                !is_inpaint_model\n            ) {\n                //@ts-ignore\n                app.showAlert('you need to add a valid ControlNet input image')\n                throw 'you need to add a valid ControlNet input image'\n            }\n\n            if (!control_net_settings['controlnet_units'][index]['module']) {\n                //@ts-ignore\n                app.showAlert('you need to select a valid ControlNet Module')\n                throw 'you need to select a valid ControlNet Module'\n            }\n\n            const is_model_free: boolean =\n                getModuleDetail()[\n                    control_net_settings['controlnet_units'][index]['module']\n                ].model_free\n\n            const has_model =\n                control_net_settings['controlnet_units'][index]['model']\n            const is_model_none: boolean =\n                has_model && has_model.toLowerCase() === 'none'\n\n            if (!is_model_free && (!has_model || is_model_none)) {\n                //@ts-ignore\n                app.showAlert('you need to select a valid ControlNet Model')\n                throw 'you need to select a valid ControlNet Model'\n            }\n        }\n\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(control_net_settings),\n        })\n\n        let json = await request.json()\n        console.log('json:', json)\n\n        //update the mask in controlNet tab\n        const numOfImages = json['images'].length\n        let numberOfAnnotations =\n            numOfImages - session_store.data.ui_settings.batch_size\n        if (numberOfAnnotations < 0) numberOfAnnotations = 0\n\n        const base64_mask = json['images'].slice(\n            numOfImages - numberOfAnnotations\n        )\n\n        let mask_index = 0\n\n        for (let index = 0; index < control_networks.length; index++) {\n            if (\n                control_networks[index] == false ||\n                mask_index >= numberOfAnnotations\n            )\n                continue\n            control_net.setControlDetectMapSrc(base64_mask[mask_index], index)\n            g_generation_session.controlNetMask[index] = base64_mask[mask_index]\n            mask_index++\n        }\n        // g_generation_session.controlNetMask = base64_mask\n\n        const standard_response =\n            await python_replacement.convertToStandardResponse(\n                control_net_settings,\n                json['images'].slice(0, numOfImages - numberOfAnnotations),\n                plugin_settings['uniqueDocumentId']\n            )\n        console.log('standard_response:', standard_response)\n\n        return standard_response\n    }\n    //REFACTOR: move to generation.js\n    static async generate(\n        settings: any\n    ): Promise<{ output_images: any; response_json: any }> {\n        let response_json\n        let output_images\n        try {\n            // const b_enable_control_net = control_net.getEnableControlNet()\n            const b_enable_control_net = control_net.isControlNetModeEnable()\n\n            if (settings_tab.store.data.selected_backend === 'Automatic1111') {\n                if (b_enable_control_net) {\n                    //use control net\n                    if (session_store.data.generation_number === 1) {\n                        session_store.data.controlnet_input_image =\n                            await io.getImg2ImgInitImage()\n                    }\n                    // console.log(\n                    //     'session_store.data.controlnet_input_image: ',\n                    //     session_store.data.controlnet_input_image\n                    // )\n\n                    response_json = await this.requestControlNetTxt2Img(\n                        settings\n                    )\n                } else {\n                    response_json = await this.requestTxt2Img(settings) //this is automatic1111 txt2img\n                }\n\n                output_images = await this.processOutput(\n                    response_json.images_info,\n                    settings\n                )\n            } else if (settings_tab.store.data.selected_backend === 'ComfyUI') {\n                //request Txt2Img from comfyui\n                settings = await mapPluginSettingsToControlNet(settings)\n                const { image_base64_list, image_url_list } =\n                    await comfyui_main_ui.generateComfyTxt2Img(settings)\n                output_images = image_base64_list\n                if (output_images) {\n                    saveOutputImagesToDriveComfy(output_images, settings)\n                }\n            }\n        } catch (e) {\n            console.warn(e)\n            console.warn('output_images: ', output_images)\n            console.warn('response_json: ', response_json)\n        }\n        return { output_images, response_json }\n    }\n    //take the output from restapi and formate it to a standard formate the plugin ui understand\n    static async processOutput(images_info: any, settings: any): Promise<any> {\n        const base64OutputImages = await saveOutputImagesToDrive(\n            images_info,\n            settings\n        )\n        return base64OutputImages\n    }\n}\n\nexport class Img2ImgMode extends Mode {\n    constructor() {\n        super()\n    }\n\n    //REFACTOR: reuse the same code for (requestControlNetTxt2Img,requestControlNetImg2Img)\n    static async requestControlNetImg2Img(plugin_settings: any) {\n        const full_url = `${g_sd_url}/sdapi/v1/img2img`\n        const control_net_settings = await mapPluginSettingsToControlNet(\n            plugin_settings\n        )\n\n        // let control_networks = 0\n        let control_networks = []\n        for (let index = 0; index < g_controlnet_max_models; index++) {\n            if (!getEnableControlNet(index)) {\n                control_networks[index] = false\n                continue\n            }\n            control_networks[index] = true\n\n            const is_inpaint_model: boolean =\n                control_net_settings['controlnet_units'][index][\n                    'module'\n                ].includes('inpaint')\n\n            if (\n                !control_net_settings['controlnet_units'][index][\n                    'input_image'\n                ] &&\n                !is_inpaint_model\n            ) {\n                //@ts-ignore\n                app.showAlert('you need to add a valid ControlNet input image')\n                throw 'you need to add a valid ControlNet input image'\n            }\n\n            if (!control_net_settings['controlnet_units'][index]['module']) {\n                //@ts-ignore\n                app.showAlert('you need to select a valid ControlNet Module')\n                throw 'you need to select a valid ControlNet Module'\n            }\n            const is_model_free: boolean =\n                getModuleDetail()[\n                    control_net_settings['controlnet_units'][index]['module']\n                ].model_free\n\n            const has_model =\n                control_net_settings['controlnet_units'][index]['model']\n            const is_model_none: boolean =\n                has_model && has_model.toLowerCase() === 'none'\n\n            if (!is_model_free && (!has_model || is_model_none)) {\n                //@ts-ignore\n                app.showAlert('you need to select a valid ControlNet Model')\n                throw 'you need to select a valid ControlNet Model'\n            }\n        }\n\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(control_net_settings),\n            // body: JSON.stringify(payload),\n        })\n\n        let json = await request.json()\n        console.log('json:', json)\n\n        //update the mask in controlNet tab\n        const numOfImages = json['images'].length\n        let numberOfAnnotations =\n            numOfImages - session_store.data.ui_settings.batch_size\n        if (numberOfAnnotations < 0) numberOfAnnotations = 0\n\n        // To fix a bug: when Ultimate SD Upscale is active and running, the detection maps won’t be retrieved.\n        // So set its value to 0 to avoid the result images being loaded in the annotation map interface.\n        if (\n            scripts.script_store.isInstalled() &&\n            scripts.script_store.is_active &&\n            scripts.script_store.selected_script_name !== 'None' &&\n            scripts.script_store.is_selected_script_available\n        ) {\n            numberOfAnnotations = 0\n        }\n        const base64_mask = json['images'].slice(\n            numOfImages - numberOfAnnotations\n        )\n\n        let mask_index = 0\n        for (let index = 0; index < control_networks.length; index++) {\n            if (\n                control_networks[index] == false ||\n                mask_index >= numberOfAnnotations\n            )\n                continue\n            control_net.setControlDetectMapSrc(base64_mask[mask_index], index)\n            g_generation_session.controlNetMask[index] = base64_mask[mask_index]\n            mask_index++\n        }\n\n        const standard_response =\n            await python_replacement.convertToStandardResponse(\n                control_net_settings,\n                json['images'].slice(0, numOfImages - numberOfAnnotations),\n                plugin_settings['uniqueDocumentId']\n            )\n        console.log('standard_response:', standard_response)\n\n        return standard_response\n    }\n\n    static async requestImg2Img(payload: any) {\n        console.log('requestImg2Img(): about to send a fetch request')\n        try {\n            let json = await python_replacement.img2ImgRequest(\n                g_sd_url,\n                payload\n            )\n            console.log('requestImg2Img json:')\n            console.dir(json)\n\n            return json\n        } catch (e) {\n            console.warn(e)\n            return {}\n        }\n    }\n    static async initializeSession(): Promise<SessionData> {\n        const selectionInfo = await psapi.getSelectionInfoExe()\n        const init_image = await io.getImg2ImgInitImage()\n        const mask = ''\n        return { selectionInfo, init_image, mask }\n    }\n    static async generate(\n        settings: any\n    ): Promise<{ output_images: any; response_json: any }> {\n        let response_json\n        let output_images\n        try {\n            //checks on index 0 as if not enabled ignores the rest\n\n            if (settings_tab.store.data.selected_backend === 'Automatic1111') {\n                const b_enable_control_net =\n                    control_net.isControlNetModeEnable()\n                if (b_enable_control_net) {\n                    //use control net\n                    response_json = await this.requestControlNetImg2Img(\n                        settings\n                    )\n                } else {\n                    response_json = await this.requestImg2Img(settings)\n                }\n                output_images = await this.processOutput(\n                    response_json.images_info,\n                    settings\n                )\n            } else if (settings_tab.store.data.selected_backend === 'ComfyUI') {\n                settings = await mapPluginSettingsToControlNet(settings)\n                if (settings?.mode === 'img2img') {\n                    const { image_base64_list, image_url_list } =\n                        await comfyui_main_ui.generateComfyImg2Img(settings)\n                    output_images = image_base64_list\n                } else if (settings?.mode === 'inpaint') {\n                    const { image_base64_list, image_url_list } =\n                        await comfyui_main_ui.generateComfyInpaint(settings)\n                    output_images = image_base64_list\n                } else if (settings?.mode === 'outpaint') {\n                    const { image_base64_list, image_url_list } =\n                        await comfyui_main_ui.generateComfyInpaint(settings)\n                    output_images = image_base64_list\n                }\n\n                if (output_images) {\n                    saveOutputImagesToDriveComfy(output_images, settings)\n                }\n            }\n        } catch (e) {\n            console.warn(e)\n            console.warn('output_images: ', output_images)\n            console.warn('response_json: ', response_json)\n        }\n\n        return { output_images, response_json }\n    }\n}\n\nexport class InpaintMode extends Img2ImgMode {\n    constructor() {\n        super()\n    }\n\n    static async initializeSession() {\n        const selectionInfo = await psapi.getSelectionInfoExe()\n        let init_image\n        let mask\n\n        try {\n            await executeAsModal(\n                async () => {\n                    if (layer_util.Layer.doesLayerExist(g_inpaint_mask_layer)) {\n                        g_inpaint_mask_layer.opacity = 100\n                    }\n                },\n                { commandName: 'Set Inpaint Layer Opacity to 100%' }\n            )\n\n            const obj = await io.getInpaintInitImageAndMask()\n            init_image = obj.init_image\n            mask = obj.mask\n        } catch (e) {\n            console.warn(e)\n        }\n\n        return { selectionInfo, init_image, mask }\n    }\n}\n\nexport class LassoInpaintMode extends Img2ImgMode {\n    constructor() {\n        super()\n    }\n\n    static async initializeSession() {\n        await selection.channelToSelectionExe('mask')\n\n        try {\n            await executeAsModal(\n                async () => {\n                    if (layer_util.Layer.doesLayerExist(g_inpaint_mask_layer)) {\n                        g_inpaint_mask_layer.opacity = 100\n                    }\n                },\n                { commandName: 'Set Inpaint Layer Opacity to 100%' }\n            )\n        } catch (e) {\n            console.warn(e)\n        }\n        const [init_image, mask] = await selection.inpaintLassoInitImageAndMask(\n            'mask',\n            sd_tab_util.helper_store.data.lasso_offset,\n            sd_tab_util.helper_store.data.make_square\n        )\n\n        const selectionInfo = await psapi.getSelectionInfoExe()\n        return { selectionInfo, init_image, mask }\n    }\n}\n\nexport class OutpaintMode extends Img2ImgMode {\n    constructor() {\n        super()\n    }\n\n    static async initializeSession() {\n        const selectionInfo = await psapi.getSelectionInfoExe()\n        let init_image\n        let mask\n\n        try {\n            const obj = await io.getOutpaintInitImageAndMask()\n            init_image = obj.init_image\n            mask = obj.mask\n        } catch (e) {\n            console.warn(e)\n        }\n\n        return { selectionInfo, init_image, mask }\n    }\n}\nexport class UpscaleMode extends Img2ImgMode {\n    static async requestExtraSingleImage(payload: any) {\n        try {\n            let json = await python_replacement.extraSingleImageRequest(\n                g_sd_url,\n                payload\n            )\n\n            return json\n        } catch (e) {\n            console.warn(e)\n            return {}\n        }\n    }\n\n    static async getSettings(session_data: any) {\n        //REFACTOR: move to generation_settings.js\n\n        let payload: any = {}\n        try {\n            const selection_info = session_data.selectionInfo\n            const upscaling_resize = extra_page_store.data.upscaling_resize\n            const width = selection_info.width * upscaling_resize\n            const height = selection_info.height * upscaling_resize\n\n            //resize_mode = 0 means \"resize to upscaling_resize\"\n            //resize_mode = 1 means \"resize to width and height\"\n            payload['resize_mode'] = extra_page_store.data.resize_mode\n            payload['show_extras_results'] =\n                extra_page_store.data.show_extras_results\n            payload['gfpgan_visibility'] =\n                extra_page_store.data.gfpgan_visibility\n            payload['codeformer_visibility'] =\n                extra_page_store.data.codeformer_visibility\n            payload['codeformer_weight'] =\n                extra_page_store.data.codeformer_weight\n            payload['upscaling_resize'] = upscaling_resize\n            payload['upscaling_resize_w'] = width\n            payload['upscaling_resize_h'] = height\n            payload['upscaling_crop'] = extra_page_store.data.upscaling_crop\n\n            const upscaler1 = extra_page_store.data.upscaler_1\n            const upscaler2 = extra_page_store.data.upscaler_2\n            payload['upscaler_1'] = upscaler1 ? upscaler1 : 'None'\n            payload['upscaler_2'] = upscaler2 ? upscaler2 : 'None'\n\n            payload['extras_upscaler_2_visibility'] =\n                extra_page_store.data.extras_upscaler_2_visibility\n            payload['upscale_first'] = extra_page_store.data.upscale_first\n\n            payload['image'] = session_data.init_image\n        } catch (e) {\n            console.error(e)\n        }\n        return payload\n    }\n\n    static async generate(settings: any): Promise<{\n        output_images: any\n        response_json: any\n    }> {\n        let response_json\n        let output_images\n        try {\n            response_json = await this.requestExtraSingleImage(settings)\n            output_images = await this.processOutput(\n                response_json.images_info,\n                settings\n            )\n        } catch (e) {\n            console.warn(e)\n            console.warn('output_images: ', output_images)\n            console.warn('response_json: ', response_json)\n        }\n        return { output_images, response_json }\n    }\n}\n"
  },
  {
    "path": "typescripts/session/progress.ts",
    "content": "import { reaction } from 'mobx'\nimport { AStore } from '../main/astore'\nimport { io, layer_util } from '../util/oldSystem'\nimport Locale from '../locale/locale'\nimport { store as session_store } from '../session/session_store'\n// import { session_ts } from '../entry'\n// import * as session_ts from '../session/session'\nimport { app, core } from 'photoshop'\n\nconst executeAsModal = core.executeAsModal\n\nexport const store = new AStore({\n    progress_layer: null,\n    timer_id: null,\n    progress_value: 0,\n    progress_image: '',\n    progress_image_height: 0,\n    progress_label: Locale('Progress..'),\n    can_update: true,\n    can_update_progress_layer: true,\n    live_progress_image: true,\n})\ndeclare let g_sd_url: string\n\nasync function updateProgressImage(progress_base64: string) {\n    try {\n        store.data.can_update_progress_layer = false\n        await executeAsModal(\n            async (context: any) => {\n                const history_id = await context.hostControl.suspendHistory({\n                    documentID: app.activeDocument.id, //TODO: change this to the session document id\n                    name: 'Progress Image',\n                })\n                await Progress.deleteProgressLayer() // delete the old progress layer\n\n                //update the progress image\n                const selection_info = await session_store.data.selectionInfo\n\n                const b_exsit = layer_util.Layer.doesLayerExist(\n                    store.data.progress_layer\n                )\n                if (!b_exsit && progress_base64) {\n                    const layer = await io.IO.base64ToLayer(\n                        progress_base64,\n                        'temp_progress_image.png',\n                        selection_info?.left,\n                        selection_info?.top,\n                        selection_info?.width,\n                        selection_info?.height\n                    )\n                    store.data.progress_layer = layer // sotre the new progress layer// TODO: make sure you delete the progress layer when the geneeration request end\n                }\n                await context.hostControl.resumeHistory(history_id)\n            },\n            { commandName: 'update progress layer' }\n        )\n    } catch (e) {\n        console.warn(e)\n    } finally {\n        store.data.can_update_progress_layer = true\n        if (!store.data.can_update) {\n            //delete the last progress layer\n            await Progress.deleteProgressLayer() // delete the old progress layer\n        }\n    }\n}\nreaction(\n    () => {\n        return store.data.progress_image\n    },\n    async (progress_image) => {\n        if (store.data.progress_image_height === 0) {\n            const { width, height } = await io.getImageSize(progress_image)\n            store.data.progress_image_height = height\n        }\n        const b_update_progress_layer = store.data.live_progress_image\n        store.data.live_progress_image = b_update_progress_layer\n\n        if (\n            b_update_progress_layer &&\n            session_store.data.ui_settings.batch_size === 1 &&\n            store.data.can_update_progress_layer &&\n            store.data.can_update // progress is still active\n        ) {\n            await updateProgressImage(progress_image)\n        }\n    }\n)\n\nexport async function requestProgress() {\n    try {\n        console.log('requestProgress: ')\n\n        const full_url = `${g_sd_url}/sdapi/v1/progress?skip_current_image=false`\n        let request = await fetch(full_url)\n        const json = await request.json()\n        // console.log('progress json:', json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        // console.log('json: ', json)\n    }\n    return null\n}\n\nexport class Progress {\n    static timer_id: any = null\n    static async deleteProgressImage() {\n        // preview.store.updateProperty('image', null)\n\n        await this.deleteProgressLayer()\n    }\n\n    static async deleteProgressLayer() {\n        try {\n            await layer_util.deleteLayers([store.data.progress_layer]) // delete the old progress layer\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    static startTimer(callback: any, interval: number = 1500) {\n        store.data.can_update = true\n        //clear the old timer if it exist\n        try {\n            store.data.progress_value = 0\n            store.data.progress_image = ''\n            store.data.progress_image_height = 0\n            store.data.progress_label = ''\n            this.timer_id = clearInterval(this.timer_id)\n        } catch (e) {\n            console.warn(e)\n        }\n\n        this.timer_id = setInterval(callback, interval)\n    }\n\n    static async endTimer(callback: any) {\n        try {\n            this.timer_id = clearInterval(this.timer_id)\n            store.data.can_update = false\n        } catch (e) {\n            console.warn(e)\n        }\n        try {\n            if (callback?.constructor.name === 'AsyncFunction') {\n                await callback() // may cause an issue if this an async\n            } else {\n                callback() // may cause an issue if this an async\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\n\nexport class ProgressAutomatic extends Progress {}\n\nexport class ProgressHordeNative {}\n"
  },
  {
    "path": "typescripts/session/session.ts",
    "content": "import { app } from 'photoshop'\n// import { control_net, preview, viewer, progress } from '../entry'\nimport * as progress from '../session/progress'\n\nimport {\n    // store as viewer_store,\n    mask_store as viewer_mask_store,\n    init_store as viewer_init_store,\n} from '../viewer/viewer_util'\nimport Locale from '../locale/locale'\nimport { store } from './session_store'\nimport { html_manip, io, python_replacement } from '../util/oldSystem'\nimport { GenerationModeEnum } from '../util/ts/enum'\nimport {\n    Img2ImgMode,\n    InpaintMode,\n    LassoInpaintMode,\n    OutpaintMode,\n    Txt2ImgMode,\n    UpscaleMode,\n} from './modes'\n\nimport { reaction } from 'mobx'\nimport {\n    resetViewer,\n    updateViewerStoreImageAndThumbnail,\n} from '../viewer/viewer_util'\nimport { sd_tab_store } from '../stores'\nimport settings_tab from '../settings/settings'\nimport comfyui_util from '../comfyui/util'\ndeclare let g_inpaint_mask_layer: any\ndeclare const g_image_not_found_url: string\ndeclare let g_current_batch_index: number\n\nreaction(\n    () => {\n        return [store.data.init_image, store.data.mask] as [string, string]\n    },\n    ([init_image, mask]: [string, string]) => {\n        html_manip.setInitImageSrc(\n            init_image\n                ? 'data:image/png;base64,' + init_image\n                : g_image_not_found_url\n        )\n        html_manip.setInitImageMaskSrc(\n            mask ? 'data:image/png;base64,' + mask : g_image_not_found_url\n        )\n    }\n)\nreaction(\n    () => {\n        return store.data.auto_photoshop_sd_extension_status\n    },\n    (auto_photoshop_sd_extension_status: boolean) => {\n        if (auto_photoshop_sd_extension_status) {\n        } else {\n            app.showAlert(\n                'Please install the Auto-Photoshop-SD Extension from Automatic1111 Extensions tab '\n            )\n        }\n    }\n)\nfunction hasSelectionChanged(new_selection: any, old_selection: any) {\n    try {\n        if (\n            new_selection.left === old_selection.left &&\n            new_selection.bottom === old_selection.bottom &&\n            new_selection.right === old_selection.right &&\n            new_selection.top === old_selection.top\n        ) {\n            return false\n        } else {\n            return true\n        }\n    } catch (e) {\n        //if any properties is missing\n\n        // console.warn(e)\n        return false\n    }\n}\n\nreaction(\n    () => {\n        return store.data.current_selection_info\n    },\n    (new_selection_info) => {\n        console.log(\n            'store.data.current_selection_info: reaction is triggered ',\n            store.data.current_selection_info\n        )\n        if (hasSelectionChanged(new_selection_info, store.data.selectionInfo)) {\n            store.data.can_generate_more = false\n        } else {\n            if (store.data.is_active) store.data.can_generate_more = true\n        }\n    }\n)\nreaction(\n    () => {\n        return store.data.is_active\n    },\n    (is_active) => {\n        console.log(\n            'store.data.is_active: reaction is triggered ',\n            store.data.is_active\n        )\n\n        if (is_active) {\n            store.data.can_generate_more = true\n        } else {\n            store.data.can_generate_more = false\n        }\n    }\n)\n\ninterface ModeToClassMap {\n    [key: string]:\n        | typeof Txt2ImgMode\n        | typeof Img2ImgMode\n        | typeof InpaintMode\n        | typeof LassoInpaintMode\n        | typeof OutpaintMode\n        | typeof UpscaleMode\n}\n\nconst modeToClassMap: ModeToClassMap = {\n    [GenerationModeEnum.Txt2Img]: Txt2ImgMode,\n    [GenerationModeEnum.Img2Img]: Img2ImgMode,\n    [GenerationModeEnum.Inpaint]: InpaintMode,\n    [GenerationModeEnum.LassoInpaint]: LassoInpaintMode,\n    [GenerationModeEnum.Outpaint]: OutpaintMode,\n    [GenerationModeEnum.Upscale]: UpscaleMode,\n}\n\nexport async function getExpandedMask(\n    mask: string,\n    expansion_value: number,\n    blur: number\n) {\n    let expanded_mask = mask\n    try {\n        let use_sharp_mask = false\n\n        if (\n            use_sharp_mask === false &&\n            mask &&\n            expansion_value >= 0 &&\n            blur >= 0\n        ) {\n            //only if mask is available and sharp_mask is off\n            // use blurry and expanded mask\n            const iterations = expansion_value\n            if (settings_tab.store.data.selected_backend === 'Automatic1111') {\n                expanded_mask = await python_replacement.maskExpansionRequest(\n                    mask,\n                    iterations,\n                    blur\n                )\n            } else if (settings_tab.store.data.selected_backend === 'ComfyUI') {\n                expanded_mask = await comfyui_util.maskExpansion(\n                    mask,\n                    iterations,\n                    blur\n                )\n            }\n        }\n\n        // return expanded_mask\n    } catch (e) {\n        console.warn(e)\n    } finally {\n        return expanded_mask\n    }\n}\n\nexport class Session {\n    constructor() {}\n    static async initializeSession(mode: GenerationModeEnum): Promise<any> {\n        try {\n            //TODO: refactor incrementSessionID() to io.ts\n            async function incrementSessionID() {\n                const uuid = await io.getUniqueDocumentId()\n                const last_session_id = await io.IOJson.loadSessionIDFromFile(\n                    uuid\n                )\n                const current_session_id = last_session_id + 1\n                await io.IOJson.saveSessionID(current_session_id, uuid)\n                return current_session_id\n            }\n            store.data.current_session_id = await incrementSessionID()\n\n            store.data.mode = mode\n            store.data.rb_mode = sd_tab_store.data.rb_mode\n\n            if (modeToClassMap.hasOwnProperty(store.data.mode)) {\n                const { selectionInfo, init_image, mask } =\n                    await modeToClassMap[store.data.mode].initializeSession()\n                store.data.selectionInfo = selectionInfo\n                if (init_image) {\n                    // const opaque_init_image = await io.fixTransparentEdges(\n                    //     init_image\n                    // )\n                    store.data.init_image = init_image\n                    // store.data.init_image = opaque_init_image\n\n                    await updateViewerStoreImageAndThumbnail(\n                        viewer_init_store,\n                        [store.data.init_image]\n                    )\n                }\n\n                if (mask) {\n                    // store.data.mask = mask\n                    const mask_monochrome =\n                        await io.convertGrayscaleToMonochrome(mask)\n                    store.data.monoMask = mask_monochrome\n                    store.data.mask = mask\n\n                    const expansion_value: number =\n                        sd_tab_store.data.mask_expansion\n\n                    const mask_blur = sd_tab_store.data.mask_blur\n                    store.data.expanded_mask = await getExpandedMask(\n                        mask,\n                        expansion_value,\n                        mask_blur\n                    )\n                    store.data.preprocessed_mask = mask\n\n                    await updateViewerStoreImageAndThumbnail(\n                        viewer_mask_store,\n\n                        [\n                            store.data.preprocessed_mask,\n                            store.data.monoMask,\n                            store.data.expanded_mask,\n                        ]\n                    )\n                }\n\n                return {\n                    selectionInfo,\n                    init_image,\n                    mask: store.data.preprocessed_mask,\n                }\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async getSettings(session_data: any) {\n        const ui_settings = await modeToClassMap[store.data.mode].getSettings(\n            session_data\n        )\n        ui_settings['session_id'] = store.data.current_session_id\n        store.data.ui_settings = ui_settings\n        return ui_settings\n    }\n    static processOutput() {}\n    static validate() {\n        if (store.data.is_active) {\n            //@ts-ignore\n            app.showAlert('You forgot to select images!')\n            return false\n        }\n        return true\n    }\n    static async initializeGeneration() {\n        store.data.is_interrupted = false\n        store.data.can_generate = false\n        store.data.generation_number += 1\n        g_current_batch_index += 1\n    }\n    static async generate(mode: GenerationModeEnum): Promise<{\n        output_images: any\n        response_json: any\n        ui_settings: any\n    }> {\n        if (!store.data.can_generate) {\n            // return null\n            throw Error(\n                'A Generation is progress, wait for to finish be fore you generate again'\n            )\n        }\n        if (store.data.is_active) {\n            //you can only use the generate button once per session\n            //@ts-ignore\n            app.showAlert(\n                'You must end the current session before starting a new one'\n            )\n            throw Error(\n                'Session is still Active. Need to end the Session before starting a new Session'\n            )\n        }\n\n        try {\n            this.initializeGeneration()\n\n            store.data.is_active = true\n            this.getProgress()\n\n            const { selectionInfo, init_image, mask } =\n                await this.initializeSession(mode)\n            var ui_settings = await this.getSettings({\n                selectionInfo,\n                init_image,\n                mask,\n                rb_mode: store.data.rb_mode, // set in initializeSession\n            })\n\n            //this should be part of initialization method or gettingSettings()\n            //calculate the expanded mask from mask\n            if (\n                [\n                    GenerationModeEnum.Inpaint,\n                    GenerationModeEnum.LassoInpaint,\n                    GenerationModeEnum.Outpaint,\n                ].includes(mode)\n            ) {\n                const expansion_value: number = sd_tab_store.data.mask_expansion\n                const mask_blur = sd_tab_store.data.mask_blur\n                store.data.expanded_mask = await getExpandedMask(\n                    mask,\n                    expansion_value,\n                    mask_blur\n                )\n\n                ui_settings['mask'] = store.data.expanded_mask\n                store.data.ui_settings = ui_settings\n            }\n            var { output_images, response_json } = await modeToClassMap[\n                mode\n            ].generate(ui_settings)\n        } catch (e) {\n            console.warn(e)\n        } finally {\n            store.data.can_generate = true\n            await this.endProgress()\n        }\n\n        return { output_images, response_json, ui_settings }\n    }\n\n    static async generateMore(): Promise<{\n        output_images: any\n        response_json: any\n        ui_settings: any\n    }> {\n        if (!store.data.can_generate) {\n            throw Error(\n                'A Generation is progress, wait for to finish be fore you generate again'\n            )\n        }\n\n        try {\n            this.initializeGeneration()\n            store.data.can_generate = false\n            this.getProgress()\n            const session_data = {\n                init_image: store.data.init_image,\n                mask: store.data.preprocessed_mask,\n                selectionInfo: store.data.selectionInfo,\n                rb_mode: store.data.rb_mode, // set in initializeSession\n            }\n            var ui_settings = await this.getSettings(session_data)\n            if (\n                [\n                    GenerationModeEnum.Inpaint,\n                    GenerationModeEnum.LassoInpaint,\n                    GenerationModeEnum.Outpaint,\n                ].includes(store.data.mode)\n            ) {\n                const expansion_value: number = sd_tab_store.data.mask_expansion\n                const mask_blur = sd_tab_store.data.mask_blur\n                store.data.expanded_mask = await getExpandedMask(\n                    session_data.mask,\n                    expansion_value,\n                    mask_blur\n                )\n\n                ui_settings['mask'] = store.data.expanded_mask\n                store.data.ui_settings = ui_settings\n            }\n            var { output_images, response_json } = await modeToClassMap[\n                store.data.mode\n            ].generate(ui_settings)\n        } catch (e) {\n            console.warn(e)\n        } finally {\n            store.data.can_generate = true\n            await this.endProgress()\n        }\n        return { output_images, response_json, ui_settings }\n    }\n    static async interrupt(): Promise<any> {\n        try {\n            await modeToClassMap[store.data.mode].interrupt()\n            store.data.is_interrupted = true\n        } catch (e) {\n            console.warn(e)\n        } finally {\n            //no need to reset progress since generate and generateMore will always finish executing after interrupt\n            // store.data.can_generate = true\n            // this.endProgress()\n        }\n    }\n    static async getProgress() {\n        // Progress.startSudoProgress()\n\n        const comfyProgress = async () => {\n            progress.store.data.progress_value += 1\n        }\n        const auto1111Progress = async () => {\n            try {\n                let json = await progress.requestProgress()\n                const can_update = progress.store.data.can_update\n                if (!can_update) {\n                    return null\n                }\n                if (json?.progress) {\n                    progress.store.updateProperty(\n                        'progress_value',\n                        json?.progress * 100\n                    )\n                }\n\n                if (json?.current_image) {\n                    progress.store.updateProperty(\n                        'progress_image',\n                        json?.current_image\n                    )\n                }\n\n                progress.store.data.progress_label = Locale('Progress...')\n\n                // console.log('progress object json: ', json)\n            } catch (e) {\n                console.warn(e)\n            }\n        }\n        const [callback, timer] =\n            settings_tab.store.data.selected_backend === 'Automatic1111'\n                ? [auto1111Progress, 2000]\n                : [comfyProgress, 1000]\n        progress.Progress.startTimer(callback, timer)\n    }\n    static async endProgress() {\n        await progress.Progress.endTimer(async () => {\n            progress.store.data.progress_value = 0\n            progress.store.data.progress_image = ''\n            progress.store.data.progress_image_height = 0\n            await progress.Progress.deleteProgressLayer()\n        })\n    }\n    static endSession() {\n        resetViewer() //may cause circular dependency\n        store.data.is_active = false //\n        store.data.init_image = ''\n        store.data.mask = ''\n        store.data.expanded_mask = ''\n        store.data.preprocessed_mask = ''\n        store.data.generation_number = 0\n        store.data.controlnet_input_image = ''\n        g_current_batch_index = -1 // first generation will add +1 to get => 0\n    }\n\n    static async getOutput() {}\n}\n"
  },
  {
    "path": "typescripts/session/session_store.ts",
    "content": "import { AStore } from '../main/astore'\nimport {\n    GenerationModeEnum,\n    ScriptMode,\n    SelectionInfoType,\n} from '../util/ts/enum'\n\ninterface AStoreUISettings {\n    batch_size: number\n    // add other properties here as needed\n}\n\ninterface AStoreData {\n    // other properties...\n\n    init_image: string\n    active_mask: string // this is the mask that is been used in the current generation\n    mask: string // the user inputted mask, also can be the mask generated by photoshop dependant on the generation mode\n    expanded_mask: string // mask after expanded\n    monoMask: string //monochrome mask, no gradation\n    preprocessed_mask: string //\n    sd_mask: string // mask send to sd as payload[mask]\n    mode: GenerationModeEnum\n    rb_mode: ScriptMode\n\n    ui_settings: AStoreUISettings\n    selectionInfo: SelectionInfoType | undefined //the session selection info\n    current_selection_info: SelectionInfoType | undefined // any new selection, could be undefined too\n    can_generate: boolean // is generation currently in progress\n    can_generate_more: boolean //\n    is_active: boolean // is session active\n    is_interrupted: boolean // did we interrupt the generation\n    generation_number: number // generation number per session, 0 mean first generation\n    controlnet_input_image: string // the controlnet the image that will controlnet load\n\n    //plugin related state:\n    auto_photoshop_sd_extension_status: boolean\n\n    doc_uuid: string\n    current_session_id: number\n    last_seed: string\n}\n\nexport const store = new AStore<AStoreData>({\n    // activeBase64InitImage: '',\n    // activeBase64Mask: '',\n    init_image: '',\n    active_mask: '', // this is the mask that is been used in the current generation\n    mask: '', // the user inputted mask, also can be the mask generated by photoshop dependant on the generation mode\n    expanded_mask: '', // mask after expanded\n    monoMask: '', //monochrome mask, no gradation\n    preprocessed_mask: '', //\n    sd_mask: '', // mask send to sd as payload[mask]\n    mode: GenerationModeEnum.Txt2Img,\n    rb_mode: ScriptMode.Txt2Img,\n    ui_settings: { batch_size: 1 },\n    selectionInfo: undefined, //the session selection info\n    current_selection_info: undefined, // any new selection, could be undefined too\n    can_generate: true, // is generation currently in progress\n    can_generate_more: false, //\n    is_active: false, // is session active\n    is_interrupted: false, // did we interrupt the generation\n    generation_number: 0, // generation number per session, 0 mean first generation\n    controlnet_input_image: '', // the controlnet the image that will controlnet load\n\n    //plugin related state:\n    auto_photoshop_sd_extension_status: true,\n    doc_uuid: '',\n    current_session_id: 0,\n    last_seed: '-1',\n})\n"
  },
  {
    "path": "typescripts/session/style/generate.css",
    "content": ".generateButtonMargin {\n    margin-top: 1px;\n    margin-bottom: 3px;\n    display: inline-block;\n}\n\n.generateColor {\n    background-color: #ff595e;\n}\n\n.generateMoreColor {\n    background-color: #6db579;\n}\n"
  },
  {
    "path": "typescripts/settings/settings.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { observer } from 'mobx-react'\nimport { AStore } from '../main/astore'\n\nimport { SpCheckBox, SpMenu, SpSlider, SpTextfield } from '../util/elements'\nimport Locale from '../locale/locale'\nimport globalStore from '../globalstore'\nimport { io } from '../util/oldSystem'\nimport { reaction } from 'mobx'\n//@ts-ignore\nimport { storage } from 'uxp'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { MaskModeEnum, ScriptMode } from '../util/ts/enum'\nimport { store as progress_store } from '../session/progress'\nimport { requestPost } from '../util/ts/api'\nimport { comfyapi } from '../entry'\n\n// import { Jimp } from '../util/oldSystem'\ndeclare const Jimp: any // make sure you import jimp before importing settings.tsx\ndeclare let g_sd_url: string\ntype InterpolationMethod = {\n    [key: string]: {\n        photoshop: string\n        jimp: string\n    }\n}\n\nconst interpolationMethods: InterpolationMethod = {\n    nearestNeighbor: {\n        photoshop: 'nearestNeighbor',\n        jimp: Jimp.RESIZE_NEAREST_NEIGHBOR,\n    },\n    bicubic: {\n        photoshop: 'bicubicAutomatic',\n        jimp: Jimp.RESIZE_BICUBIC,\n    },\n    bilinear: {\n        photoshop: 'bilinear',\n        jimp: Jimp.RESIZE_BILINEAR,\n    },\n}\n\nenum ExtensionTypeEnum {\n    ProxyServer = 'proxy_server',\n    Auto1111Extension = 'auto1111_extension',\n    None = 'none',\n}\nconst config = {\n    [ExtensionTypeEnum.ProxyServer]: {\n        title: \"use the proxy server, need to run 'start_server.bat' \",\n        value: ExtensionTypeEnum.ProxyServer,\n        label: 'Proxy Server',\n    },\n    [ExtensionTypeEnum.Auto1111Extension]: {\n        title: 'use Automatic1111 Photoshop SD Extension, need to install the extension in Auto1111',\n        value: ExtensionTypeEnum.Auto1111Extension,\n        label: 'Auto1111 Extension',\n    },\n    [ExtensionTypeEnum.None]: {\n        title: 'Use the Plugin Only No Additional Component',\n        value: ExtensionTypeEnum.None,\n        label: 'None',\n    },\n}\n\nfunction extensionTypeName(extension_type: ExtensionTypeEnum) {\n    return extension_type\n        .split('_')\n        .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n        .join(' ')\n}\ninterface AStoreData {\n    scale_interpolation_method: typeof interpolationMethods.bilinear\n    should_log_to_file: boolean\n    delete_log_file_timer_id: ReturnType<typeof setInterval> | undefined\n    b_borders_or_corners: MaskModeEnum\n    use_image_cfg_scale_slider: boolean\n    extension_type: ExtensionTypeEnum\n    use_sharp_mask: boolean\n    use_prompt_shortcut: boolean\n    bTurnOffServerStatusAlert: boolean\n    CLIP_stop_at_last_layers: number\n    use_smart_object: boolean\n    selected_backend: 'Automatic1111' | 'ComfyUI'\n    comfy_url: string\n}\nexport const store = new AStore<AStoreData>({\n    scale_interpolation_method: interpolationMethods.bilinear,\n    should_log_to_file:\n        JSON.parse(storage.localStorage.getItem('should_log_to_file')) || false,\n    delete_log_file_timer_id: undefined,\n    b_borders_or_corners: MaskModeEnum.Transparent,\n    use_image_cfg_scale_slider: false,\n    extension_type: ExtensionTypeEnum.Auto1111Extension,\n    use_sharp_mask: false,\n    use_prompt_shortcut: true,\n    bTurnOffServerStatusAlert:\n        JSON.parse(storage.localStorage.getItem('bTurnOffServerStatusAlert')) ||\n        false,\n    CLIP_stop_at_last_layers: 1,\n    use_smart_object: true, // true to keep layer as smart objects, false to rasterize them\n    // selected_backend: 'Automatic1111' as 'Automatic1111' | 'ComfyUI',\n    selected_backend: (storage.localStorage.getItem('selected_backend') ||\n        'ComfyUI') as 'Automatic1111' | 'ComfyUI',\n    comfy_url:\n        storage.localStorage.getItem('comfy_url') || 'http://127.0.0.1:8188',\n})\n\nfunction onShouldLogToFileChange(event: any) {\n    try {\n        const should_log_to_file: boolean = event.target.checked\n        store.data.should_log_to_file = should_log_to_file\n        storage.localStorage.setItem('should_log_to_file', should_log_to_file)\n        if (should_log_to_file && !store.data.delete_log_file_timer_id) {\n            store.data.delete_log_file_timer_id = setDeleteLogTimer()\n        } else {\n            //don't log and clear delete file timer\n            try {\n                clearInterval(\n                    store.data.delete_log_file_timer_id as ReturnType<\n                        typeof setInterval\n                    >\n                )\n                store.data.delete_log_file_timer_id = undefined\n            } catch (e) {\n                console.warn(e)\n            }\n        }\n\n        //@ts-ignore\n        setLogMethod(should_log_to_file)\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction setDeleteLogTimer() {\n    const timer_id = setInterval(async () => {\n        await io.deleteFileIfLargerThan('log.txt', 200)\n    }, 2 * 60 * 1000)\n    console.log('setDeleteLogTimer() timer_id :', timer_id)\n    return timer_id\n}\nasync function postOptions(options: Object) {\n    try {\n        const full_url = `${g_sd_url}/sdapi/v1/options`\n        await requestPost(full_url, options)\n    } catch (e) {\n        console.warn('failed postOptions at : ', g_sd_url, options, e)\n    }\n}\n\ninterface Options {\n    [key: string]: number\n    CLIP_stop_at_last_layers: number\n}\n\nasync function getOptions(): Promise<Options | null> {\n    const full_url = `${g_sd_url}/sdapi/v1/options`\n    try {\n        const response = await fetch(full_url)\n        if (response.status === 404) return null\n        return await response.json()\n    } catch (error) {\n        console.error(`Error fetching from ${full_url}:`, error)\n        return null\n    }\n}\n\n@observer\nexport class Settings extends React.Component<{}> {\n    async componentDidMount(): Promise<void> {\n        if (store.data.selected_backend === 'Automatic1111') {\n            const options = await getOptions()\n\n            store.data.CLIP_stop_at_last_layers =\n                options?.CLIP_stop_at_last_layers ??\n                store.data.CLIP_stop_at_last_layers\n        }\n    }\n\n    render() {\n        return (\n            <div style={{ width: '100%' }}>\n                <sp-label>ComfyUI Url:</sp-label>\n                <SpTextfield\n                    type=\"text\"\n                    placeholder=\"http://127.0.0.1:8188\"\n                    // value={config.default}\n                    value={store.data.comfy_url}\n                    onChange={(event: any) => {\n                        // store.data.search_query = event.target.value\n\n                        let url = event.target.value.trim() // remove leading and trailing white spaces\n                        url = url.replace(/[/\\\\]$/, '')\n                        console.log(url)\n                        store.data.comfy_url = url\n                        comfyapi.comfy_api.setUrl(store.data.comfy_url)\n                        storage.localStorage.setItem(\n                            'comfy_url',\n                            store.data.comfy_url\n                        )\n                    }}\n                ></SpTextfield>\n                <sp-radio-group>\n                    {['Automatic1111', 'ComfyUI'].map(\n                        (backend: any, index: number) => {\n                            return (\n                                <sp-radio\n                                    key={index}\n                                    title={backend}\n                                    value={backend}\n                                    onClick={(evt: any) => {\n                                        store.data.selected_backend =\n                                            evt.target.value\n                                        storage.localStorage.setItem(\n                                            'selected_backend',\n                                            store.data.selected_backend\n                                        )\n                                    }}\n                                    checked={\n                                        store.data.selected_backend === backend\n                                            ? true\n                                            : void 0\n                                    }\n                                >\n                                    {backend}\n                                </sp-radio>\n                            )\n                        }\n                    )}\n                </sp-radio-group>\n                <SpMenu\n                    title=\"select an interploation method for resizing images\"\n                    items={Object.keys(interpolationMethods)}\n                    label_item=\"Select Interpolation Method\"\n                    selected_index={Object.keys(interpolationMethods).findIndex(\n                        (key) => {\n                            return (\n                                interpolationMethods[key].photoshop ===\n                                    store.data.scale_interpolation_method\n                                        .photoshop &&\n                                interpolationMethods[key].jimp ===\n                                    store.data.scale_interpolation_method.jimp\n                            )\n                        }\n                    )}\n                    onChange={(id: any, value: any) => {\n                        store.updateProperty(\n                            'scale_interpolation_method',\n                            interpolationMethods[value.item]\n                        )\n                    }}\n                ></SpMenu>\n\n                <div style={{ width: '100%' }}>\n                    <sp-label>{Locale('select language:')}</sp-label>\n                </div>\n                <SpMenu\n                    title=\"select language\"\n                    items={['en_US', 'zh_CN']}\n                    label_item=\"select language\"\n                    selected_index={['en_US', 'zh_CN'].indexOf(\n                        globalStore.Locale\n                    )}\n                    onChange={(id: any, value: any) => {\n                        globalStore.Locale = value.item\n                        localStorage.setItem('last_selected_locale', value.item)\n                        console.log(\n                            localStorage.getItem('last_selected_locale')\n                        )\n                    }}\n                ></SpMenu>\n                <div style={{}}>\n                    <SpCheckBox\n                        style={{\n                            marginRight: '10px',\n                        }}\n                        onChange={onShouldLogToFileChange}\n                        checked={store.data.should_log_to_file}\n                    >\n                        {Locale('Log Errors To File')}\n                    </SpCheckBox>\n                </div>\n\n                <sp-radio-group\n                    style={{ display: 'flex' }}\n                    selected={store.data.b_borders_or_corners}\n                    onClick={(event: any) => {\n                        store.data.b_borders_or_corners = event.target.value\n                    }}\n                >\n                    <sp-label slot=\"label\">\n                        {Locale('Mask Layer Mode:')}\n                    </sp-label>\n                    {[\n                        {\n                            label: 'fully transparent',\n                            value: MaskModeEnum.Transparent,\n                        },\n                        { label: 'keep borders', value: MaskModeEnum.Borders },\n                        { label: 'keep corners', value: MaskModeEnum.Corners },\n                    ].map((mode: any, index: number) => {\n                        // console.log('mode:', mode.label, ' index:', index)\n                        return (\n                            <sp-radio\n                                key={`mode-${index}`}\n                                checked={\n                                    store.data.b_borders_or_corners ===\n                                    mode.value\n                                        ? true\n                                        : void 0\n                                }\n                                value={mode.value}\n                            >\n                                {Locale(mode.label)}\n                            </sp-radio>\n                        )\n                    })}\n                </sp-radio-group>\n                <SpCheckBox\n                    style={{\n                        marginRight: '10px',\n                    }}\n                    onChange={(evt: any) => {\n                        progress_store.data.live_progress_image =\n                            evt.target.checked\n                    }}\n                    checked={progress_store.data.live_progress_image}\n                >\n                    {\n                        //@ts-ignore\n                        Locale('Live Progress Image')\n                    }\n                </SpCheckBox>\n                <div>\n                    <sp-checkbox\n                        id=\"chUseImageCfgScaleSlider\"\n                        title=\"image cfg slider for pix2pix mode\"\n                        value={store.data.use_image_cfg_scale_slider}\n                        onClick={(evt: any) => {\n                            store.data.use_image_cfg_scale_slider =\n                                evt.target.checked\n                        }}\n                        style={{ display: 'inline-flex' }}\n                    >\n                        {Locale('Image Cfg Scale Slider')}\n                    </sp-checkbox>\n                </div>\n                <div>\n                    <sp-checkbox\n                        id=\"chUseSharpMask\"\n                        checked={store.data.use_sharp_mask}\n                        onClick={(evt: any) => {\n                            store.data.use_sharp_mask = evt.target.checked\n                        }}\n                    >\n                        {Locale('use sharp mask')}\n                    </sp-checkbox>\n                </div>\n                <div>\n                    <sp-radio-group selected={store.data.extension_type}>\n                        <sp-label slot=\"label\">\n                            {Locale('Select Extension:')}\n                        </sp-label>\n                        {[\n                            ExtensionTypeEnum.ProxyServer,\n                            ExtensionTypeEnum.Auto1111Extension,\n                            ExtensionTypeEnum.None,\n                        ].map((extension_type, index: number) => {\n                            return (\n                                <sp-radio\n                                    key={index}\n                                    title={config[extension_type].title}\n                                    class=\"rbExtensionType\"\n                                    value={config[extension_type].value}\n                                    checked={\n                                        store.data.extension_type ===\n                                        config[extension_type].value\n                                            ? true\n                                            : void 0\n                                    }\n                                    onClick={(evt: any) => {\n                                        store.data.extension_type =\n                                            evt.target.value\n                                    }}\n                                >\n                                    {Locale(config[extension_type].label)}\n                                </sp-radio>\n                            )\n                        })}\n                    </sp-radio-group>\n                </div>\n                <div>\n                    <sp-checkbox\n                        id=\"chTurnOffServerStatusAlert\"\n                        checked={\n                            store.data.bTurnOffServerStatusAlert\n                                ? true\n                                : undefined\n                        }\n                        onClick={(evt: any) => {\n                            store.data.bTurnOffServerStatusAlert =\n                                evt.target.checked\n                            storage.localStorage.setItem(\n                                'bTurnOffServerStatusAlert',\n                                evt.target.checked\n                            )\n                        }}\n                    >\n                        {Locale('Turn Off Server Status Alert')}\n                    </sp-checkbox>\n                </div>\n                <div>\n                    <SpSlider\n                        show-value=\"false\"\n                        min={1}\n                        max={12}\n                        value={store.data.CLIP_stop_at_last_layers}\n                        onInput={(evt: any) => {\n                            store.data.CLIP_stop_at_last_layers =\n                                evt.target.value\n                        }}\n                        onChange={async (evt: any) => {\n                            console.log(\n                                'should update clip skip through the option endpoint'\n                            )\n                            await postOptions({\n                                CLIP_stop_at_last_layers:\n                                    store.data.CLIP_stop_at_last_layers,\n                            })\n                        }}\n                        title=\"clip skip: use 1 for none, 2 for skipping one layer\"\n                    >\n                        <sp-label slot=\"label\">\n                            {Locale('Clip Skip: ')}\n                        </sp-label>\n                        <sp-label slot=\"label\">\n                            {store.data.CLIP_stop_at_last_layers}\n                        </sp-label>\n                    </SpSlider>\n                </div>\n                <div>\n                    <sp-checkbox\n                        checked={store.data.use_smart_object ? true : undefined}\n                        id=\"chUseSmartObject\"\n                        onClick={(evt: any) => {\n                            store.data.use_smart_object = evt.target.checked\n                                ? true\n                                : false\n                        }}\n                    >\n                        {Locale('Smart Object')}\n                    </sp-checkbox>\n                </div>\n            </div>\n        )\n    }\n}\nconst containerNode = document.getElementById('reactSettingsContainer')!\nconst root = ReactDOM.createRoot(containerNode)\n\nroot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <Settings></Settings>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n\nprogress_store.data.live_progress_image\n\nexport default {\n    store: store,\n}\n"
  },
  {
    "path": "typescripts/settings/vae.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { observer } from 'mobx-react'\nimport { AStore } from '../main/astore'\nimport { SpMenu } from '../util/elements'\n\nimport { api, python_replacement } from '../util/oldSystem'\nconst { getExtensionUrl } = python_replacement\nimport '../locale/locale-for-old-html'\nimport { ErrorBoundary } from '../util/errorBoundary'\n\ndeclare let g_sd_url: string\n\nexport const store = new AStore({\n    vae_model_list: [] as string[],\n    current_vae: '' as string,\n})\n\n@observer\nexport class VAEComponent extends React.Component<{\n    // store: AStore\n}> {\n    componentDidMount(): void {}\n    changeVAEModel(vae_model: string) {\n        try {\n            const full_url = `${g_sd_url}/sdapi/v1/options`\n            api.requestPost(full_url, { sd_vae: vae_model })\n        } catch (e) {\n            console.warn('changeVAEModel: vae_model: ', vae_model, e)\n        }\n    }\n    handleRefresh() {\n        populateVAE()\n    }\n    render(): React.ReactNode {\n        return (\n            <div style={{ display: 'flex' }}>\n                <SpMenu\n                    title=\"vae models\"\n                    items={store.data.vae_model_list}\n                    // style=\"width: 199px; margin-right: 5px\"\n                    label_item=\"Select A VAE\"\n                    // id={'model_list'}\n                    selected_index={store.data.vae_model_list.indexOf(\n                        store.data.current_vae\n                    )}\n                    onChange={(id: any, value: any) => {\n                        // script_store.setSelectedScript(value.item)\n                        console.log('onChange value: ', value)\n                        this.changeVAEModel(value.item)\n                    }}\n                ></SpMenu>\n                <button\n                    className=\"btnSquare refreshButton\"\n                    title=\"Refresh VAE Models List\"\n                    onClick={this.handleRefresh}\n                ></button>\n            </div>\n        )\n    }\n}\nconst vaeContainerNode = document.getElementById('settingsVAEContainer')!\nconst vaeRoot = ReactDOM.createRoot(vaeContainerNode)\n\nasync function requestGetVAE() {\n    const full_url = `${g_sd_url}/sdapi/v1/options`\n\n    const options = await api.requestGet(full_url)\n    return options?.sd_vae\n}\nexport async function populateVAE() {\n    try {\n        const extension_url = getExtensionUrl()\n\n        const full_url = `${extension_url}/vae/list`\n        const vae_models = (await api.requestGet(full_url)) || []\n\n        console.log('populateVAE vae_models: ', vae_models)\n        store.updateProperty('vae_model_list', vae_models)\n\n        const current_vae = await requestGetVAE()\n        if (current_vae && vae_models.includes(current_vae)) {\n            store.updateProperty('current_vae', current_vae)\n        }\n    } catch (e) {\n        console.warn('populateVAE():', e)\n    }\n}\n\nvaeRoot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <VAEComponent></VAEComponent>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n\nexport default {\n    store,\n    populateVAE,\n}\n"
  },
  {
    "path": "typescripts/stores.ts",
    "content": "export { store as session_store } from './session/session_store'\nexport { store as sd_tab_store } from './sd_tab/util'\nexport { mask_store } from './viewer/viewer_util'\n"
  },
  {
    "path": "typescripts/tool_bar/style/tool_bar.css",
    "content": "/* styles.css */\n#_tool_bar_container button:not(:last-child) {\n    margin-bottom: 3px;\n}\n"
  },
  {
    "path": "typescripts/tool_bar/tool_bar.tsx",
    "content": "import { observer } from 'mobx-react'\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { general, html_manip, io, psapi } from '../util/oldSystem'\nimport {\n    default_preset,\n    loadPresetSettings,\n    store as sd_tab_store,\n} from '../sd_tab/util'\nimport { requestPost } from '../util/ts/api'\nimport ControlNetStore from '../controlnet/store'\nimport { AStore } from '../main/astore'\n\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport './style/tool_bar.css'\nimport { presetToStore } from '../util/ts/io'\nimport { multiPrompts } from '../entry'\nimport { activateSessionSelectionArea } from '../util/ts/selection'\ndeclare let g_sd_url: string\n\nexport const store = new AStore({\n    at_controlnet_unit_index: 0,\n})\nasync function clipInterrogate() {\n    try {\n        const width = sd_tab_store.data.width\n        const height = sd_tab_store.data.height\n        const selectionInfo = await psapi.getSelectionInfoExe()\n\n        const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(\n            width,\n            height,\n            selectionInfo,\n            true\n        )\n\n        const url = `${g_sd_url}/sdapi/v1/interrogate`\n\n        const payload = {\n            image: base64,\n            model: 'clip',\n        }\n        const result_json = await requestPost(url, payload)\n        console.log(result_json)\n        return result_json\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function onInterrogate(evt: any) {\n    // start sudo timer after 1 seconds delay\n    let sudo_timer_id\n    setTimeout(() => {\n        sudo_timer_id = general.sudoTimer('Interrogate')\n    }, 1000)\n    const interrogate_result = await clipInterrogate()\n\n    if (interrogate_result.caption) {\n        html_manip.autoFillInPrompt(interrogate_result.caption)\n    }\n\n    // after the clipInterrogate finish stop the timer\n\n    html_manip.updateProgressBarsHtml(0, 'No work in progress')\n    clearInterval(sudo_timer_id)\n    sudo_timer_id = null\n}\n\nfunction scrollToPreview() {\n    try {\n        document\n            .querySelector('#search_second_panel > div.previewContainer')!\n            .scrollIntoView()\n        // document.getElementById('taPrompt').scrollIntoView()\n    } catch (e) {\n        console.error(e)\n    }\n}\nfunction scrollToHistory() {\n    try {\n        document\n            .querySelector('#search_second_panel > div#historyImagesContainer')!\n            .scrollIntoView()\n    } catch (e) {\n        console.error(e)\n    }\n}\nfunction scrollToLexica() {\n    try {\n        document\n            .querySelector('#search_second_panel > div.lexicaContainer')!\n            .scrollIntoView()\n    } catch (e) {\n        console.error(e)\n    }\n}\n\n@observer\nclass ToolBar extends React.Component<{}> {\n    componentDidMount(): void {\n        console.log('ToolBar did mount')\n    }\n    render() {\n        return (\n            <div id=\"_tool_bar_container\">\n                <button\n                    className=\"btnSquare layerToSelection btnLayerToSelection\"\n                    title=\"Move and reSize the highlighted layer to fit into the Selection Area \"\n                    style={{ marginRight: '3px' }}\n                    onClick={async (evt: any) => {\n                        try {\n                            const isSelectionAreaValid =\n                                await psapi.checkIfSelectionAreaIsActive()\n                            if (isSelectionAreaValid) {\n                                const validSelection = isSelectionAreaValid\n                                await psapi.layerToSelection(validSelection)\n                            } else {\n                                await psapi.promptForMarqueeTool()\n                            }\n                        } catch (e) {\n                            console.error(e)\n                        }\n                    }}\n                ></button>\n                <button\n                    title=\"create a snapshot of what you see on the canvas and place on a new layer\"\n                    className=\"btnSquare snapshotButton\"\n                    style={{ marginRight: '3px' }}\n                    onClick={async (evt: any) => {\n                        try {\n                            await psapi.snapshot_layerExe()\n                        } catch (e) {\n                            console.warn(e)\n                        }\n                    }}\n                ></button>\n                <button\n                    className=\"btnSquare resetButton btnResetSettings\"\n                    title=\"reset the ui settings to their default values\"\n                    style={{ marginRight: '3px' }}\n                    onClick={(evt: any) => {\n                        try {\n                            multiPrompts.setPrompt({\n                                positive: '',\n                                negative: '',\n                            })\n                            loadPresetSettings(default_preset)\n                        } catch (e) {\n                            console.warn(e)\n                        }\n                    }}\n                ></button>\n                <button\n                    className=\"btnSquare interrogateButton\"\n                    id=\"btnInterrogate\"\n                    title=\"Interrogate the selected area, convert Image to Prompt\"\n                    style={{ marginRight: '3px' }}\n                    onClick={onInterrogate}\n                ></button>\n                <button\n                    className=\"btnSquare svgButton selectionAreaButton\"\n                    id=\"btnSelectionArea\"\n                    style={{ marginRight: '3px' }}\n                    title=\"Reselect the selection area for the current session\"\n                    onClick={activateSessionSelectionArea}\n                ></button>\n                <button\n                    id=\"scrollToPreview\"\n                    className=\"btnSquare svgButton\"\n                    title=\"Quickly jump to the preview section\"\n                    onClick={scrollToPreview}\n                >\n                    P\n                </button>\n                <div id=\"scrollToControlNetUnitContainer\">\n                    <button\n                        className=\"btnSquare svgButton\"\n                        onClick={() => {\n                            try {\n                                const units = document.querySelectorAll(\n                                    '#controlNetTabParentContainer .collapsible'\n                                )\n                                const units_data =\n                                    ControlNetStore.controlNetUnitData.map(\n                                        (data, index) => ({\n                                            enabled: data.enabled,\n                                            index,\n                                        })\n                                    )\n\n                                // Find the next enabled unit\n                                let counter = 0\n                                while (\n                                    !units_data[\n                                        store.data.at_controlnet_unit_index %\n                                            units.length\n                                    ].enabled &&\n                                    counter < units.length\n                                ) {\n                                    store.data.at_controlnet_unit_index += 1\n                                    counter += 1\n                                }\n\n                                if (counter < units.length) {\n                                    store.data.at_controlnet_unit_index =\n                                        store.data.at_controlnet_unit_index %\n                                        units.length\n                                    units[\n                                        store.data.at_controlnet_unit_index\n                                    ].scrollIntoView()\n                                    store.data.at_controlnet_unit_index += 1\n                                }\n                            } catch (e) {\n                                console.warn(e)\n                            }\n                        }}\n                        title=\"Quickly jump to the active ControlNet Unit\"\n                    >\n                        C\n                    </button>\n                    <button\n                        id=\"\"\n                        className=\"btnSquare svgButton\"\n                        title=\"Quickly jump to the History Panel\"\n                        onClick={scrollToHistory}\n                    >\n                        H\n                    </button>\n                    <button\n                        id=\"\"\n                        className=\"btnSquare svgButton\"\n                        title=\"Quickly jump to the Lexica Panel\"\n                        onClick={scrollToLexica}\n                    >\n                        L\n                    </button>\n                </div>\n            </div>\n        )\n    }\n}\n\nconst container = document.getElementById('toolBarContainer')!\nconst root = ReactDOM.createRoot(container)\n\nroot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <ToolBar></ToolBar>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Visit https://aka.ms/tsconfig to read more about this file */\n\n    /* Projects */\n    // \"incremental\": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */\n    // \"composite\": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */\n    // \"tsBuildInfoFile\": \"./.tsbuildinfo\",              /* Specify the path to .tsbuildinfo incremental compilation file. */\n    // \"disableSourceOfProjectReferenceRedirect\": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */\n    // \"disableSolutionSearching\": true,                 /* Opt a project out of multi-project reference checking when editing. */\n    // \"disableReferencedProjectLoad\": true,             /* Reduce the number of projects loaded automatically by TypeScript. */\n\n    /* Language and Environment */\n    \"target\": \"ES2020\",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */\n    // \"lib\": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */\n    \"jsx\": \"react\",                                /* Specify what JSX code is generated. */\n    \"experimentalDecorators\": true,                   /* Enable experimental support for legacy experimental decorators. */\n    // \"emitDecoratorMetadata\": true,                    /* Emit design-type metadata for decorated declarations in source files. */\n    // \"jsxFactory\": \"\",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */\n    // \"jsxFragmentFactory\": \"\",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */\n    // \"jsxImportSource\": \"\",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */\n    // \"reactNamespace\": \"\",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */\n    // \"noLib\": true,                                    /* Disable including any library files, including the default lib.d.ts. */\n    // \"useDefineForClassFields\": true,                  /* Emit ECMAScript-standard-compliant class fields. */\n    // \"moduleDetection\": \"auto\",                        /* Control what method is used to detect module-format JS files. */\n\n    /* Modules */\n    \"module\": \"commonjs\",                                /* Specify what module code is generated. */\n    // \"rootDir\": \"./\",                                  /* Specify the root folder within your source files. */\n    // \"moduleResolution\": \"node10\",                     /* Specify how TypeScript looks up a file from a given module specifier. */\n    // \"baseUrl\": \"./\",                                  /* Specify the base directory to resolve non-relative module names. */\n    // \"paths\": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */\n    // \"rootDirs\": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */\n    \"typeRoots\": [\"./@types\",\"./types\", \"../node_modules/@types\"],                                  /* Specify multiple folders that act like './node_modules/@types'. */\n    // \"types\": [],                                      /* Specify type package names to be included without being referenced in a source file. */\n    \n    // \"allowUmdGlobalAccess\": true,                     /* Allow accessing UMD globals from modules. */\n    // \"moduleSuffixes\": [],                             /* List of file name suffixes to search when resolving a module. */\n    // \"allowImportingTsExtensions\": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */\n    // \"resolvePackageJsonExports\": true,                /* Use the package.json 'exports' field when resolving package imports. */\n    // \"resolvePackageJsonImports\": true,                /* Use the package.json 'imports' field when resolving imports. */\n    // \"customConditions\": [],                           /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */\n    \"resolveJsonModule\": true,                        /* Enable importing .json files. */\n    // \"allowArbitraryExtensions\": true,                 /* Enable importing files with any extension, provided a declaration file is present. */\n    // \"noResolve\": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */\n\n    /* JavaScript Support */\n    \"allowJs\": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */\n    // \"checkJs\": true,                                  /* Enable error reporting in type-checked JavaScript files. */\n    // \"maxNodeModuleJsDepth\": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */\n\n    /* Emit */\n    // \"declaration\": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */\n    // \"declarationMap\": true,                           /* Create sourcemaps for d.ts files. */\n    // \"emitDeclarationOnly\": true,                      /* Only output d.ts files and not JavaScript files. */\n    \"sourceMap\": true,                                /* Create source map files for emitted JavaScript files. */\n    // \"inlineSourceMap\": true,                          /* Include sourcemap files inside the emitted JavaScript. */\n    // \"outFile\": \"./\",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */\n    \"outDir\": \"../typescripts/dist\",                                   /* Specify an output folder for all emitted files. */\n    // \"removeComments\": true,                           /* Disable emitting comments. */\n    // \"noEmit\": true,                                   /* Disable emitting files from a compilation. */\n    // \"importHelpers\": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */\n    // \"importsNotUsedAsValues\": \"remove\",               /* Specify emit/checking behavior for imports that are only used for types. */\n    // \"downlevelIteration\": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */\n    // \"sourceRoot\": \"\",                                 /* Specify the root path for debuggers to find the reference source code. */\n    // \"mapRoot\": \"\",                                    /* Specify the location where debugger should locate map files instead of generated locations. */\n    // \"inlineSources\": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */\n    // \"emitBOM\": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */\n    // \"newLine\": \"crlf\",                                /* Set the newline character for emitting files. */\n    // \"stripInternal\": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */\n    // \"noEmitHelpers\": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */\n    // \"noEmitOnError\": true,                            /* Disable emitting files if any type checking errors are reported. */\n    // \"preserveConstEnums\": true,                       /* Disable erasing 'const enum' declarations in generated code. */\n    // \"declarationDir\": \"./\",                           /* Specify the output directory for generated declaration files. */\n    // \"preserveValueImports\": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */\n\n    /* Interop Constraints */\n    // \"isolatedModules\": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */\n    // \"verbatimModuleSyntax\": true,                     /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */\n    // \"allowSyntheticDefaultImports\": true,             /* Allow 'import x from y' when a module doesn't have a default export. */\n    \"esModuleInterop\": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */\n    // \"preserveSymlinks\": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */\n    \"forceConsistentCasingInFileNames\": true,            /* Ensure that casing is correct in imports. */\n\n    /* Type Checking */\n    \"strict\": true,                                      /* Enable all strict type-checking options. */\n    // \"noImplicitAny\": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */\n    // \"strictNullChecks\": true,                         /* When type checking, take into account 'null' and 'undefined'. */\n    // \"strictFunctionTypes\": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */\n    // \"strictBindCallApply\": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */\n    // \"strictPropertyInitialization\": true,             /* Check for class properties that are declared but not set in the constructor. */\n    // \"noImplicitThis\": true,                           /* Enable error reporting when 'this' is given the type 'any'. */\n    // \"useUnknownInCatchVariables\": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */\n    // \"alwaysStrict\": true,                             /* Ensure 'use strict' is always emitted. */\n    // \"noUnusedLocals\": true,                           /* Enable error reporting when local variables aren't read. */\n    // \"noUnusedParameters\": true,                       /* Raise an error when a function parameter isn't read. */\n    // \"exactOptionalPropertyTypes\": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */\n    // \"noImplicitReturns\": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */\n    // \"noFallthroughCasesInSwitch\": true,               /* Enable error reporting for fallthrough cases in switch statements. */\n    // \"noUncheckedIndexedAccess\": true,                 /* Add 'undefined' to a type when accessed using an index. */\n    // \"noImplicitOverride\": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */\n    // \"noPropertyAccessFromIndexSignature\": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */\n    // \"allowUnusedLabels\": true,                        /* Disable error reporting for unused labels. */\n    // \"allowUnreachableCode\": true,                     /* Disable error reporting for unreachable code. */\n\n    /* Completeness */\n    // \"skipDefaultLibCheck\": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */\n    \"skipLibCheck\": true                                 /* Skip type checking all .d.ts files. */\n  },\n  \"exclude\": [\"../jimp\"],\n  // \"include\": [\"./typescripts/@types/custom.d.ts\"]\n}\n"
  },
  {
    "path": "typescripts/ultimate_sd_upscaler/config.ts",
    "content": "export let ui_config = {\n    tile_width: {\n        minimum: 0,\n        maximum: 2048,\n        step: 64,\n        label: 'Tile width',\n        value: 512,\n    },\n    tile_height: {\n        minimum: 0,\n        maximum: 2048,\n        step: 64,\n        label: 'Tile height',\n        value: 0,\n    },\n    mask_blur: {\n        minimum: 0,\n        maximum: 64,\n        step: 1,\n        label: 'Mask blur',\n        value: 8,\n    },\n    padding: { minimum: 0, maximum: 128, step: 1, label: 'Padding', value: 32 },\n\n    seams_fix_denoise: {\n        label: 'Denoise',\n        minimum: 0,\n        maximum: 1,\n        step: 0.01,\n        value: 0.35,\n        visible: false,\n        interactive: true,\n    },\n\n    seams_fix_width: {\n        label: 'Width',\n        minimum: 0,\n        maximum: 128,\n        step: 1,\n        value: 64,\n        visible: false,\n        interactive: true,\n    },\n    seams_fix_mask_blur: {\n        label: 'Mask blur',\n        minimum: 0,\n        maximum: 64,\n        step: 1,\n        value: 4,\n        visible: false,\n        interactive: true,\n    },\n    seams_fix_padding: {\n        label: 'Padding',\n        minimum: 0,\n        maximum: 128,\n        step: 1,\n        value: 16,\n        visible: false,\n        interactive: true,\n    },\n    redraw_mode: {\n        label: 'Type',\n        choices: ['Linear', 'Chess', 'None'],\n        type: 'index',\n        value: 0,\n    },\n    save_upscaled_image: {\n        label: 'Upscaled',\n        value: true,\n    },\n    save_seams_fix_image: {\n        label: 'Seams fix',\n        value: false,\n    },\n\n    seams_fix_type: {\n        label: 'Type',\n        choices: [\n            'None',\n            'Band pass',\n            'Half tile offset pass',\n            'Half tile offset pass + intersections',\n        ],\n        type: 'index',\n        value: 3,\n    },\n\n    target_size_type: {\n        label: 'Target size type',\n        choices: [\n            'From img2img2 settings',\n            'Custom size',\n            'Scale from image size',\n        ],\n        type: 'index',\n        value: 2,\n    },\n\n    custom_width: {\n        label: 'Custom width',\n        minimum: 64,\n        maximum: 8192,\n        step: 64,\n        value: 2048,\n        visible: false,\n        interactive: true,\n    },\n    custom_height: {\n        label: 'Custom height',\n        minimum: 64,\n        maximum: 8192,\n        step: 64,\n        value: 2048,\n        visible: false,\n        interactive: true,\n    },\n    custom_scale: {\n        label: 'Scale',\n        minimum: 1,\n        maximum: 16,\n        step: 0.01,\n        value: 2,\n        visible: false,\n        interactive: true,\n    },\n\n    upscaler_index: {\n        label: 'Upscaler',\n        choices: [],\n        type: 'index',\n        value: 0,\n    },\n}\n"
  },
  {
    "path": "typescripts/ultimate_sd_upscaler/scripts.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { makeAutoObservable, toJS } from 'mobx'\nimport { observer } from 'mobx-react'\n\nimport { SpMenu } from '../util/elements'\nimport * as ultimate_sd_upscale_script from './ultimate_sd_upscaler'\nimport { ScriptMode } from './ultimate_sd_upscaler'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport Locale from '../locale/locale'\nexport function toJsFunc(store: any) {\n    return toJS(store)\n}\n\nclass ScriptStore {\n    scripts_list\n    disabled: boolean[]\n    selected_script_name\n    is_selected_script_available: boolean\n    selected_store: any\n    is_active: boolean\n    selected_args_name: string[]\n    mode: ScriptMode\n\n    scripts: any = {\n        None: { store: null, args_names: [], mode: [] },\n        'ultimate sd upscale': {\n            store: ultimate_sd_upscale_script.ultimate_sd_upscaler_store,\n            args_names: ultimate_sd_upscale_script.script_args_ordered,\n            mode: ultimate_sd_upscale_script.script_mode,\n        },\n    }\n\n    constructor() {\n        this.scripts_list = ['None', ultimate_sd_upscale_script.script_name]\n        this.disabled = [false, true]\n        this.selected_script_name = 'None'\n        this.is_selected_script_available = true\n        this.selected_store = null\n        this.is_active = true\n        this.selected_args_name = []\n        this.mode = ScriptMode.Txt2Img\n\n        makeAutoObservable(this)\n    }\n    setSelectedScript(name: string) {\n        this.selected_script_name = name\n        this.selected_store = this.scripts[name].store\n        this.selected_args_name = this.scripts[name].args_names\n        this.is_selected_script_available = true\n    }\n    setIsActive(new_value: boolean) {\n        this.is_active = new_value\n    }\n    updateProperty(id: any, value: any) {}\n\n    orderedValues() {\n        const values: any = []\n        if (!this.selected_store) return values\n\n        for (const key of this.selected_args_name) {\n            // console.log(key, this.data[key])\n            values.push((this.selected_store.data as any)[key])\n        }\n        return values\n    }\n    setDisabled(newDisabled: boolean[]) {\n        console.log('this.disabled:', this.disabled)\n        console.log('newDisabled:', newDisabled)\n\n        this.disabled = newDisabled\n    }\n    setMode(newMode: ScriptMode) {\n        this.mode = newMode\n\n        // let index = 0\n        // Object.keys(this.scripts).forEach((key, index) => {\n        //     const script = this.scripts[key]\n        //     this.disabled[index] = script.mode.includes(newMode) ? false : true\n\n        //     // console.log(key, script)\n        // })\n        const names = Object.keys(this.scripts)\n        let index = 0\n        for (let name of names) {\n            const script = this.scripts[name]\n            this.disabled[index] = script.mode.includes(newMode) ? false : true\n            index += 1\n        }\n\n        this.disabled[0] = false // None is always enabled\n        const selected_index = this.scripts_list.indexOf(\n            this.selected_script_name\n        )\n        this.is_selected_script_available = !this.disabled?.[selected_index]\n        this.setDisabled([...this.disabled])\n    }\n    isInstalled() {\n        return this.selected_store?.isInstalled() ?? false\n    }\n}\n\nexport const script_store = new ScriptStore()\n\n@observer\nclass ScriptComponent extends React.Component<{}> {\n    render(): React.ReactNode {\n        // const script_message = index !== -1 ? script_store.disabled[index] : undefined;\n        const script_message =\n            script_store.is_selected_script_available ? undefined : (\n                <span style={{ color: '#ff595e' }}>\n                    {'the script is not available in the current Mode'}\n                </span>\n            )\n\n        return (\n            <>\n                <SpMenu\n                    title=\"Scripts\"\n                    items={script_store.scripts_list}\n                    disabled_items={script_store.disabled}\n                    // style=\"width: 199px; margin-right: 5px\"\n                    label_item=\"Select A Script\"\n                    id={'script_list'}\n                    onChange={(id: any, value: any) => {\n                        script_store.setSelectedScript(value.item)\n                    }}\n                />\n                <div>\n                    {script_message}\n\n                    {/* {script_store.disabled.map((value, index) => (\n                        <li key={index}> {value ? 'true' : 'false'}</li>\n                    ))} */}\n                </div>\n                <sp-checkbox\n                    checked={script_store.is_active ? true : undefined}\n                    onClick={(event: React.ChangeEvent<HTMLInputElement>) => {\n                        script_store.setIsActive(event.target.checked)\n                    }}\n                >\n                    {Locale('Activate')}\n                </sp-checkbox>\n                <>\n                    {script_store.selected_script_name === 'None' && <></>}\n                    {script_store.selected_script_name ===\n                        ultimate_sd_upscale_script.script_name && (\n                        <ultimate_sd_upscale_script.UltimateSDUpscalerForm\n                            store={\n                                // ultimate_sd_upscale_script.ultimate_sd_upscaler_store\n                                script_store.scripts[\n                                    script_store.selected_script_name\n                                ].store\n                            }\n                        />\n                    )}\n                    {/* ... other conditions for other components */}\n                </>\n            </>\n        )\n    }\n}\nconst domNode = document.getElementById('scriptsContainer')!\nconst root = ReactDOM.createRoot(domNode)\n\nroot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n            <ScriptComponent></ScriptComponent>\n        </div>\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/ultimate_sd_upscaler/ultimate_sd_upscaler.tsx",
    "content": "import React, { ReactEventHandler } from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { action, makeAutoObservable, reaction, toJS } from 'mobx'\nimport { Provider, inject, observer } from 'mobx-react'\n\nimport { SliderType, SpMenu, SpSliderWithLabel } from '../util/elements'\n\nimport { ui_config } from './config'\nimport { api } from '../util/oldSystem'\n\nconst { requestGet } = api\ndeclare let g_sd_url: string\n\nexport let script_name: string = 'ultimate sd upscale'\nexport enum ScriptMode {\n    Txt2Img = 'txt2img',\n    Img2Img = 'img2img',\n    Inpaint = 'inpaint',\n    Outpaint = 'outpaint',\n}\n\nexport let script_mode = [\n    ScriptMode.Img2Img,\n    ScriptMode.Inpaint,\n    ScriptMode.Outpaint,\n]\ninterface UltimateSDUpscalerData {\n    _: string\n    tile_width: number\n    tile_height: number\n    mask_blur: number\n    padding: number\n    seams_fix_width: number\n    seams_fix_denoise: number\n    seams_fix_padding: number\n    upscaler_index: number\n    save_upscaled_image: boolean\n    redraw_mode: number\n    save_seams_fix_image: boolean\n    seams_fix_mask_blur: number\n    seams_fix_type: number\n    target_size_type: number\n    custom_width: number\n    custom_height: number\n    custom_scale: number\n    is_installed: boolean\n}\nexport const script_args_ordered = [\n    '_',\n    'tile_width',\n    'tile_height',\n    'mask_blur',\n    'padding',\n    'seams_fix_width',\n    'seams_fix_denoise',\n    'seams_fix_padding',\n    'upscaler_index',\n    'save_upscaled_image',\n    'redraw_mode',\n    'save_seams_fix_image',\n    'seams_fix_mask_blur',\n    'seams_fix_type',\n    'target_size_type',\n    'custom_width',\n    'custom_height',\n    'custom_scale',\n]\n\n//for some reason oldSystem.sdapi is empty {}, could be caused by a circular dependency\n//so I've copy pasted requestGetUpscalers() to the ultimate sd upscaler module, as a temporary solution\nasync function requestGetUpscalers() {\n    console.log('requestGetUpscalers: ')\n    let json = []\n    const full_url = `${g_sd_url}/sdapi/v1/upscalers`\n    try {\n        let request = await fetch(full_url)\n        json = await request.json()\n        console.log('upscalers json:')\n        console.dir(json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\n\nclass UltimateSDUpscalerStore {\n    data: UltimateSDUpscalerData\n\n    is_active: boolean\n    constructor(data: UltimateSDUpscalerData) {\n        this.data = data\n\n        this.is_active = false\n        makeAutoObservable(this)\n    }\n    setIsActive(b_value: boolean) {\n        this.is_active = b_value\n    }\n\n    updateProperty(key: keyof UltimateSDUpscalerData, value: any) {\n        ;(this.data as any)[key] = value\n    }\n\n    isInstalled() {\n        return this.data?.is_installed ?? false\n    }\n    toJsFunc() {\n        return toJS(this)\n    }\n}\n\nconst configValues = Object.entries(ui_config).reduce(\n    (acc, [key, value]) => ({ ...acc, [key]: value.value }),\n    {}\n)\nconst default_values: any = {\n    _: '',\n    ...configValues,\n    is_installed: false,\n}\nexport const ultimate_sd_upscaler_store = new UltimateSDUpscalerStore(\n    default_values\n)\n\n@observer\nexport class UltimateSDUpscalerForm extends React.Component<{\n    store: UltimateSDUpscalerStore\n}> {\n    // slider1Ref = React.createRef<SpSliderWithLabel>()\n    // slider2Ref = React.createRef<SpSliderWithLabel>()\n    state = {\n        items: ['Item 1', 'Item 2', 'Item 3'],\n        sd_upscalers: [],\n    }\n    async componentDidMount(): Promise<void> {\n        if (await this.isInstalled()) {\n            await this.getUpscalers()\n        }\n    }\n    handleUpdateItems = () => {\n        this.setState({\n            items: ['New Item 1', 'New Item 2', 'New Item 3'],\n        })\n    }\n\n    handleSliderChange = (key: any, newValue: any) => {\n        this.props.store.updateProperty(key, newValue)\n    }\n    handleMenuChange = (key: any, new_index_value_pair: any) => {\n        let config = ui_config[key as keyof typeof ui_config] as any\n        if ('type' in config) {\n            let value =\n                config.type === 'index'\n                    ? new_index_value_pair['index']\n                    : new_index_value_pair['item']\n            this.props.store.updateProperty(key, value)\n        }\n    }\n\n    async getUpscalers() {\n        try {\n            const sd_upscalers_json = await requestGetUpscalers()\n            const sd_upscalers = sd_upscalers_json.map(\n                (upscaler: any) => upscaler.name\n            )\n            this.setState({ sd_upscalers: sd_upscalers })\n            return sd_upscalers\n        } catch (e) {\n            console.warn('ultimate sd upscaler getUpscalers(): ', e)\n        }\n    }\n\n    handleRefresh = async () => {\n        if (await this.isInstalled()) {\n            await this.getUpscalers()\n        }\n    }\n    async isInstalled() {\n        const full_url = `${g_sd_url}/sdapi/v1/scripts`\n        const scripts = await requestGet(full_url)\n        const is_installed =\n            scripts?.txt2img?.includes(script_name) ||\n            scripts?.img2img?.includes(script_name) ||\n            false\n\n        console.log('is_installed: ', is_installed)\n        this.props.store.updateProperty('is_installed', is_installed)\n        return is_installed\n    }\n\n    renderScaleSlider() {\n        switch (this.props.store.data.target_size_type) {\n            case ui_config.target_size_type.choices.indexOf(\n                'Scale from image size'\n            ):\n                return (\n                    <SpSliderWithLabel\n                        label={ui_config.custom_scale.label}\n                        output_value={this.props.store.data.custom_scale}\n                        id={'custom_scale'}\n                        out_min={ui_config.custom_scale.minimum}\n                        out_max={ui_config.custom_scale.maximum}\n                        onSliderInput={this.handleSliderChange}\n                        steps={0.01}\n                        slider_type={SliderType.Float}\n                    />\n                )\n            case ui_config.target_size_type.choices.indexOf('Custom size'):\n                return (\n                    <>\n                        <SpSliderWithLabel\n                            label={ui_config.custom_width.label}\n                            output_value={this.props.store.data.custom_width}\n                            id={'custom_width'}\n                            out_min={ui_config.custom_width.minimum}\n                            out_max={ui_config.custom_width.maximum}\n                            onSliderInput={this.handleSliderChange}\n                            steps={ui_config.custom_width.step}\n                            slider_type={SliderType.Integer}\n                        />\n                        <SpSliderWithLabel\n                            label={ui_config.custom_height.label}\n                            output_value={this.props.store.data.custom_height}\n                            id={'custom_height'}\n                            out_min={ui_config.custom_height.minimum}\n                            out_max={ui_config.custom_height.maximum}\n                            onSliderInput={this.handleSliderChange}\n                            steps={ui_config.custom_height.step}\n                            slider_type={SliderType.Integer}\n                        />\n                    </>\n                )\n            default:\n                return void 0\n        }\n    }\n\n    render() {\n        if (!this.props.store.data.is_installed) {\n            return (\n                <div>\n                    <sp-label class=\"missing-error\">\n                        Script is not available; Make sure to install it from\n                        Automatic1111 webui\n                    </sp-label>\n                    <button\n                        className=\"btnSquare refreshButton\"\n                        title=\"Refresh the Ultimte SD Upscale script\"\n                        onClick={this.handleRefresh}\n                    ></button>\n                </div>\n            )\n        }\n\n        const ids = [\n            'tile_width',\n            'tile_height',\n            'mask_blur',\n            'padding',\n        ] as const\n        // let config = ui_config[ids as keyof typeof ui_config] as any\n        const group_1_sliders = ids.map((id) => (\n            <SpSliderWithLabel\n                key={id}\n                id={id}\n                show-value={false}\n                steps={ui_config[id].step}\n                out_min={ui_config[id].minimum}\n                out_max={ui_config[id].maximum}\n                output_value={this.props.store.data[id]}\n                title={ui_config[id].label}\n                label={ui_config[id].label}\n                onSliderInput={this.handleSliderChange}\n            />\n        ))\n        const seamfix_ids = [\n            'seams_fix_denoise',\n            'seams_fix_width',\n            'seams_fix_mask_blur',\n            'seams_fix_padding',\n        ] as const\n        const seamfix_sliders = seamfix_ids.map((id) => (\n            <SpSliderWithLabel\n                key={id}\n                id={id}\n                show-value={false}\n                steps={ui_config[id].step}\n                out_min={ui_config[id].minimum}\n                out_max={ui_config[id].maximum}\n                output_value={this.props.store.data[id]}\n                title={ui_config[id].label}\n                label={ui_config[id].label}\n                onSliderInput={this.handleSliderChange}\n                slider_type={\n                    Number.isInteger(ui_config[id].step)\n                        ? SliderType.Integer\n                        : SliderType.Float\n                }\n            />\n        ))\n        return (\n            <div>\n                <SpMenu\n                    title=\"Stable Diffusion Upscalers\"\n                    items={this.state.sd_upscalers}\n                    label_item=\"Select Upscaler\"\n                    id={'upscaler_index'}\n                    onChange={this.handleMenuChange}\n                    selected_index={this.props.store.data.upscaler_index}\n                />\n                <SpMenu\n                    title={ui_config.target_size_type.label}\n                    id={'target_size_type'}\n                    items={ui_config.target_size_type.choices}\n                    label_item={'Select ' + ui_config.target_size_type.label}\n                    onChange={this.handleMenuChange}\n                    selected_index={this.props.store.data.target_size_type}\n                />\n                {this.renderScaleSlider()}\n                <div>\n                    <sp-checkbox\n                        checked={\n                            this.props.store.data.save_upscaled_image\n                                ? true\n                                : undefined\n                        }\n                        onClick={(\n                            event: React.ChangeEvent<HTMLInputElement>\n                        ) => {\n                            this.props.store.updateProperty(\n                                'save_upscaled_image',\n                                event.target.checked\n                            )\n                        }}\n                    >\n                        {ui_config.save_upscaled_image.label}\n                    </sp-checkbox>\n                    <sp-checkbox\n                        checked={\n                            this.props.store.data.save_seams_fix_image\n                                ? true\n                                : undefined\n                        }\n                        onClick={(\n                            event: React.ChangeEvent<HTMLInputElement>\n                        ) => {\n                            this.props.store.updateProperty(\n                                'save_seams_fix_image',\n                                event.target.checked\n                            )\n                        }}\n                    >\n                        {ui_config.save_seams_fix_image.label}\n                    </sp-checkbox>\n                </div>\n                {group_1_sliders}\n                <SpMenu\n                    title={'Seams Fix Type'}\n                    id={'seams_fix_type'}\n                    items={ui_config.seams_fix_type.choices}\n                    label_item=\"Select Seams Fix Type\"\n                    onChange={this.handleMenuChange}\n                    selected_index={this.props.store.data.seams_fix_type}\n                />\n                {seamfix_sliders}\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "typescripts/util/collapsible.tsx",
    "content": "import React, { CSSProperties, ComponentType } from 'react'\n// import ReactDOM from 'react-dom'\n\nimport { useState, ReactNode } from 'react'\nimport Locale from '../locale/locale'\ninterface CollapsibleProps {\n    label: string\n    labelStyle?: React.CSSProperties\n    containerStyle?: React.CSSProperties\n    defaultIsOpen?: boolean\n    checked?: boolean\n    checkboxCallback?: (checked: boolean) => void\n    children: ReactNode\n}\n\nexport function Collapsible({\n    label,\n    labelStyle,\n    containerStyle,\n    defaultIsOpen = false,\n    checkboxCallback,\n    checked,\n    children,\n}: CollapsibleProps) {\n    const [isOpen, setIsOpen] = useState(defaultIsOpen)\n\n    const handleToggle = () => {\n        setIsOpen(!isOpen)\n    }\n\n    return (\n        /*useObserver(()=>*/ <div>\n            <div\n                className=\"collapsible\"\n                style={containerStyle}\n                onClick={handleToggle}\n            >\n                <span className=\"truncate\" style={labelStyle}>\n                    {label}\n                </span>\n\n                <span\n                    style={{ float: 'right', display: 'flex' }}\n                    className=\"triangle\"\n                >\n                    {checkboxCallback && checked !== void 0 ? (\n                        <input\n                            type=\"checkbox\"\n                            className=\"minimal-checkbox\"\n                            onClick={(event) => {\n                                event.stopPropagation()\n                            }}\n                            onChange={(event: any) => {\n                                checkboxCallback(event.target.checked)\n                            }}\n                            checked={checked}\n                        />\n                    ) : (\n                        void 0\n                    )}\n\n                    <span>{isOpen ? '∨' : '<'}</span>\n                </span>\n            </div>\n            {/* {isOpen && <div>{children}</div>} */}\n            <div style={{ display: isOpen ? 'block' : 'none' }}>{children}</div>\n        </div>\n    )\n}\n"
  },
  {
    "path": "typescripts/util/elements.tsx",
    "content": "import React, { CSSProperties, ComponentType } from 'react'\n// import ReactDOM from 'react-dom'\nimport ReactDOM from 'react-dom/client'\nimport Locale from '../locale/locale'\nimport { observer } from 'mobx-react'\n// import { versions } from 'uxp'\nexport { ReactComponent as MoveToCanvasSvg } from '../../icon/move_to_canvas.svg'\nexport { ReactComponent as PenSvg } from '../../icon/pen.svg'\nexport { ReactComponent as PreviewSvg } from '../../icon/preview.svg'\nexport { ReactComponent as ImageSearchSvg } from '../../icon/search_button.svg'\n\ndeclare global {\n    namespace JSX {\n        interface IntrinsicElements {\n            'sp-picker': any\n            'sp-menu': any\n            'sp-menu-item': any\n            'sp-label': any\n            'sp-checkbox': any\n            'sp-slider': any\n            'sp-radio-group': any\n            'sp-radio': any\n            'sp-divider': any\n            'sp-detail': any\n            'sp-textarea': any\n            'sp-textfield': any\n            'sp-action-button': any\n            'sp-progressbar': any\n            'sp-popover': any\n            'sp-dialog': any\n        }\n    }\n}\nfunction mapRange(\n    x: number,\n    in_min: number,\n    in_max: number,\n    out_min: number,\n    out_max: number\n) {\n    const mappedValue =\n        ((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min\n    return mappedValue\n}\nexport enum SliderType {\n    Integer = 'integer',\n    Float = 'float',\n}\n@observer\nexport class SpSliderWithLabel extends React.Component<{\n    onSliderChange?: any\n    onSliderInput?: any\n    id?: string\n    'show-value'?: boolean\n    steps?: number\n    in_min?: number\n    in_max?: number\n    out_min: number\n    out_max: number\n    // value?: number\n    title?: string\n    label?: string\n    output_value?: number // can be use to represent sd value\n    // slider_value?: number // it's slider value can be from 1 to 100\n    slider_type?: SliderType\n    disabled?: boolean\n}> {\n    // const [sliderValue,setSliderValue] = useState<number>(0)\n    state = { output_value: this.props.output_value || 0, slider_value: 0 }\n    steps: number\n    in_min: number\n    in_max: number\n    out_min: number\n    out_max: number\n    slider_type: SliderType\n    constructor(props: any) {\n        super(props)\n        this.steps = this.props.steps || 1\n        // this.out_min = this.props.out_min || this.in_min\n        this.out_min = this.props.out_min\n        this.out_max = this.props.out_max\n\n        // const temp_out_max = this.props.out_max || this.props.in_max || 99\n        this.in_min = this.props.in_min || 0\n        this.in_max = Math.round((this.out_max - this.out_min) / this.steps)\n        this.slider_type = this.props.slider_type || SliderType.Integer\n    }\n\n    componentDidMount(): void {\n        const slider_value = this.outputValueToStep(this.state.output_value)\n        this.setState({ slider_value: slider_value })\n    }\n    stepToOutputValue(slider_step: number) {\n        let to_value = mapRange(\n            slider_step,\n            this.in_min,\n            this.in_max,\n            this.out_min,\n            this.out_max\n        )\n        if (this.slider_type === SliderType.Integer)\n            to_value = Math.round(to_value)\n\n        return to_value\n    }\n    outputValueToStep(output_value: number) {\n        let slider_step = mapRange(\n            output_value,\n            this.out_min,\n            this.out_max,\n            this.in_min,\n            this.in_max\n        )\n        // if (this.slider_type === SliderType.Integer)\n        slider_step = Math.round(slider_step)\n        return slider_step\n    }\n    setSliderValue(newValue: any) {\n        let to_value = mapRange(\n            newValue,\n            this.in_min,\n            this.in_max,\n            this.out_min,\n            this.out_max\n        )\n\n        if (this.slider_type === SliderType.Integer)\n            to_value = Math.round(to_value)\n\n        this.setState({ output_value: to_value })\n    }\n\n    onSliderValueInputHandler(event: React.ChangeEvent<HTMLInputElement>) {\n        const newValue: string = event.target.value\n\n        let output_value = this.stepToOutputValue(parseInt(newValue))\n        this.setState({ output_value: output_value })\n        if (this.props.onSliderInput && this.props.id) {\n            this.props.onSliderInput(this.props.id, output_value)\n        } else if (this.props.onSliderInput) {\n            this.props.onSliderInput(output_value)\n        }\n    }\n    onSliderValueChangeHandler(event: React.ChangeEvent<HTMLInputElement>) {\n        const newValue: string = event.target.value\n\n        let output_value = this.stepToOutputValue(parseInt(newValue))\n        this.setState({ output_value: output_value })\n        if (this.props.onSliderChange && this.props.id) {\n            this.props.onSliderChange(this.props.id, output_value)\n        } else if (this.props.onSliderChange) {\n            this.props.onSliderChange(output_value)\n        }\n    }\n\n    handleNum2Change = (event: React.ChangeEvent<HTMLInputElement>) => {}\n\n    render() {\n        return (\n            // <div>\n            //     <\n            //     <sp-detail>VERSIONS</sp-detail>\n            //     <div>{versions.plugin}</div>\n            // </div>\n            <div>\n                <SpSlider\n                    show-value=\"false\"\n                    disabled={this.props.disabled ? true : void 0}\n                    min={this.in_min}\n                    max={this.in_max}\n                    value={this.state.slider_value}\n                    title={this.props?.title ?? ''}\n                    onInput={\n                        this.props.onSliderInput\n                            ? this.onSliderValueInputHandler.bind(this)\n                            : void 0\n                    }\n                    onChange={this.onSliderValueChangeHandler.bind(this)}\n                >\n                    <sp-label slot=\"label\">\n                        {Locale(this.props.label as any)}:\n                    </sp-label>\n                    <sp-label\n                        slot=\"label\"\n                        // id=\"lControlNetWeight_0\"\n                        class=\"lControlNetWeight_\"\n                    >\n                        {this.state.output_value}\n                    </sp-label>\n                </SpSlider>\n            </div>\n        )\n    }\n}\n\nexport class SpMenu extends React.Component<{\n    id?: string\n\n    title?: string\n    style?: CSSProperties\n    items?: string[]\n    disabled?: boolean\n    disabled_items?: boolean[]\n    label_item?: string\n    onChange?: any\n    selected_index?: number\n    size?: string\n}> {\n    state = {\n        selectedItem: this.props.items ? this.props.items[0] : undefined,\n    }\n\n    componentDidUpdate(prevProps: any) {\n        // console.log('prevProps.items: ', prevProps.items)\n        // console.log('this.props.items: ', this.props.items)\n        // if (prevProps.items !== this.props.items) {\n        //     const spMenu = this.spMenuRef.current\n        //     if (spMenu) {\n        //         spMenu.innerHTML = ''\n        //     }\n        // }\n    }\n    handleItemClick = (item: string, index: number) => {\n        console.log('clicked item: ', item)\n        console.log('clicked index: ', index)\n        this.setState({ selectedItem: item })\n        if (this.props.onChange && this.props.id) {\n            this.props.onChange(this.props.id, { index: index, item: item })\n        } else if (this.props.onChange) {\n            this.props.onChange(null, { index: index, item: item })\n        }\n    }\n    handleMakeSelection = (item: string) => {\n        console.log('handleMakeSelection: item ', item)\n        this.setState({ selectedItem: item })\n    }\n\n    render() {\n        return (\n            <sp-picker\n                title={this.props.title}\n                size={this.props.size || 'm'}\n                style={this.props.style}\n                disabled={this.props.disabled ? 'disabled' : undefined}\n                // style={{ width: '199px', marginRight: '5px' }}\n            >\n                <sp-menu id={this.props.id} slot=\"options\">\n                    {this.props.label_item && (\n                        <sp-menu-item\n                            disabled=\"disabled\"\n                            key={-1}\n                            data-index={-1}\n                            selected\n                        >\n                            {this.props.label_item}\n                        </sp-menu-item>\n                    )}\n                    {this.props.items?.map((item, index: number) => (\n                        <sp-menu-item\n                            key={item}\n                            data-index={index}\n                            selected={\n                                this.props.selected_index !== undefined &&\n                                this.props.selected_index !== null &&\n                                this.props.selected_index === index\n                                    ? 'selected'\n                                    : undefined\n                            }\n                            disabled={\n                                this.props.disabled_items?.[index]\n                                    ? 'disabled'\n                                    : undefined\n                            }\n                            onClick={() => {\n                                this.handleItemClick(item, index)\n                            }}\n                        >\n                            {item}\n                        </sp-menu-item>\n                    ))}\n                </sp-menu>\n            </sp-picker>\n        )\n    }\n}\nclass PhotoshopElem extends React.Component<{ [key: string]: any }, {}> {\n    protected elem: Element | null = null\n\n    protected curEvents: { [key: string]: (evt: Event) => any } = {}\n\n    componentDidMount(): void {\n        this.updateEventListener()\n    }\n\n    // componentDidUpdate(): void {\n    //     this.updateEventListener()\n    // }\n\n    updateEventListener() {\n        if (!this.elem) throw new Error('elem is not rendered with ref')\n\n        const [, newEvent] = this.splitProps(this.props)\n\n        Object.keys(this.curEvents).forEach((evkey) => {\n            if (this.curEvents[evkey] != newEvent[evkey]) {\n                this.elem?.removeEventListener(evkey, this.curEvents[evkey])\n            }\n        })\n        Object.keys(newEvent).forEach((evkey) => {\n            this.elem?.addEventListener(evkey, newEvent[evkey])\n        })\n    }\n\n    componentWillUnmount(): void {\n        Object.keys(this.curEvents).forEach((evkey) => {\n            this.elem?.removeEventListener(evkey, this.curEvents[evkey])\n        })\n    }\n    splitProps(props: any): [any, any] {\n        const attr: any = {}\n        const event: any = {}\n        Object.keys(props).forEach((propKey: string) => {\n            if (propKey.startsWith('on')) {\n                const key = propKey[2].toLocaleLowerCase() + propKey.slice(3)\n                event[key] = props[propKey]\n            } else {\n                attr[propKey] = props[propKey]\n            }\n        })\n        return [attr, event]\n    }\n}\nexport class SpPicker extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-picker\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-picker>\n        )\n    }\n}\nexport class SpMenuComponent extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-menu\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-menu>\n        )\n    }\n}\nexport class SpMenuItem extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-menu-item\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-menu-item>\n        )\n    }\n}\nexport class SpLabel extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-label\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-label>\n        )\n    }\n}\nexport class SpCheckBox extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        if (!attr['checked']) delete attr['checked']\n        return (\n            <sp-checkbox\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-checkbox>\n        )\n    }\n}\nexport class SpSlider extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-slider\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-slider>\n        )\n    }\n}\nexport class SpTextfield extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-textfield\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-textfield>\n        )\n    }\n}\nexport class SpRadioGroup extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-radio-group\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-radio-group>\n        )\n    }\n}\nexport class SpRadio extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-radio\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-radio>\n        )\n    }\n}\nexport class SpDivider extends PhotoshopElem {\n    render() {\n        const [attr] = this.splitProps(this.props)\n        return (\n            <sp-divider\n                ref={(elem: Element) => (this.elem = elem)}\n                {...attr}\n            ></sp-divider>\n        )\n    }\n}\n\nexport class Thumbnail extends React.Component<{\n    style?: any\n    children: React.ReactNode\n}> {\n    render() {\n        return (\n            <div style={this.props?.style} className=\"viewer-image-container\">\n                {this.props.children}\n            </div>\n        )\n    }\n}\n\nexport class ActionButtonSVG extends React.Component<{\n    onClick?: any\n    ComponentType: ComponentType\n    title?: string\n}> {\n    render() {\n        if (!this.props.ComponentType) {\n            return null\n        }\n\n        return (\n            <sp-action-button\n                onClick={this.props?.onClick}\n                style={{\n                    padding: 0,\n                    maxWidth: '32px',\n                    maxHeight: '32px' /* display: none; */,\n                }}\n                class=\"thumbnail-image-button\"\n                title={this.props.title ?? void 0}\n            >\n                <div slot=\"icon\" style={{ fill: 'currentColor' }}>\n                    {<this.props.ComponentType />}\n                </div>\n            </sp-action-button>\n        )\n    }\n}\n\ninterface ScriptInstallComponentProps {\n    onRefreshHandler: any\n}\nexport const ScriptInstallComponent = observer(\n    ({ onRefreshHandler }: ScriptInstallComponentProps) => {\n        return (\n            <div>\n                <sp-label class=\"missing-error\">\n                    Script is not available; Make sure to install it from\n                    Automatic1111 webui\n                </sp-label>\n                <button\n                    className=\"btnSquare refreshButton btnResetSettings\"\n                    title=\"Refresh the ADetailer Extension\"\n                    onClick={onRefreshHandler}\n                ></button>\n            </div>\n        )\n    }\n)\n\n@observer\nexport class SearchableMenu extends React.Component<{\n    allItems: string[]\n    placeholder: string\n    onChange?: any\n    selected_item?: string\n    onSelectItemFailure?: any\n    // default_value?: string\n    // searchQuery: string\n}> {\n    state = {\n        selectedItem: this.props.allItems ? this.props.allItems[0] : undefined,\n        searchItems: this.props.allItems,\n        // searchQuery: this.props.searchQuery,\n        searchQuery: '',\n        openMenu: false,\n    }\n    selectItem(selected_item: string) {\n        let final_value = this.props.allItems.includes(selected_item)\n            ? selected_item\n            : this.props.onSelectItemFailure && this.props.onSelectItemFailure()\n\n        this.setState({ searchQuery: final_value })\n    }\n    componentDidMount(): void {\n        if (this.props.selected_item) {\n            // console.log('selected_item has changed:', this.props.selected_item)\n            this.selectItem(this.props.selected_item)\n        }\n    }\n    componentDidUpdate(prevProps: any, prevState: { searchQuery: string }) {\n        if (prevState.searchQuery !== this.state.searchQuery) {\n            this.searchItem(this.state.searchQuery)\n        }\n        if (prevProps.selected_item !== this.props.selected_item) {\n            console.log('selected_item has changed:', this.props.selected_item)\n\n            if (this.props.selected_item !== undefined) {\n                this.selectItem(this.props.selected_item)\n            }\n        }\n    }\n\n    // searchItem = (event: React.KeyboardEvent<HTMLInputElement>) => {\n    searchItem = (searchQuery: string) => {\n        console.log('onInput')\n\n        // const filter = event.currentTarget.value.toUpperCase()\n        const filter = searchQuery.toUpperCase()\n\n        const searchItems = this.props.allItems.filter((item) =>\n            item.toUpperCase().includes(filter)\n        )\n        this.setState({ searchItems: searchItems })\n\n        console.log(\n            'this.props.searchItems.length: ',\n            this.state.searchItems.length\n        )\n\n        this.setState({\n            openMenu: this.state.searchItems.length > 0 ? true : false,\n        })\n\n        console.log('this.state.openMenu: ', this.state.openMenu)\n    }\n    render() {\n        return (\n            <div\n                style={{\n                    display: 'flex',\n                    width: '100%',\n                    zIndex: 1000,\n                    // position: 'absolute',\n                }}\n            >\n                <div style={{ position: 'relative', flex: 1, width: '100%' }}>\n                    <SpTextfield\n                        type=\"text\"\n                        title={this.state.searchQuery}\n                        style={{ width: '100%' }}\n                        value={this.state.searchQuery}\n                        placeholder={this.props.placeholder}\n                        onInput={(evt: any) => {\n                            this.setState({ searchQuery: evt.target.value })\n                            // this.searchItem(evt.taret)\n                            console.log('onInput:', evt.target.value)\n\n                            console.log(\n                                'this.state.searchQuery: ',\n                                this.state.searchQuery\n                            )\n                        }}\n                        onChange={(evt: any) => {\n                            this.setState({ searchQuery: evt.target.value })\n                            console.log('onChange:', evt.target.value)\n\n                            console.log(\n                                'this.state.searchQuery: ',\n                                this.state.searchQuery\n                            )\n                        }}\n                        onFocus={(evt: any) => {\n                            console.log('onFocus:', evt.target.value)\n\n                            this.setState({\n                                searchItems: this.props.allItems,\n                            })\n                            this.setState({ openMenu: true })\n                            console.log(\n                                'this.state.searchQuery: ',\n                                this.state.searchQuery\n                            )\n                        }}\n                        onBlur={(evt: any) => {\n                            setTimeout(\n                                () => {\n                                    console.log('onBlur:', evt.target.value)\n\n                                    const state_values: Record<string, any> = {}\n                                    if (\n                                        !this.props.allItems.includes(\n                                            this.state.searchQuery\n                                        )\n                                    ) {\n                                        state_values.searchQuery = ''\n\n                                        if (this.props.onSelectItemFailure) {\n                                            state_values.searchQuery =\n                                                this.props.onSelectItemFailure()\n                                        }\n                                    }\n                                    state_values.openMenu = false\n                                    this.setState(state_values)\n\n                                    console.log(\n                                        'this.state.searchQuery: ',\n                                        this.state.searchQuery\n                                    )\n                                },\n\n                                200\n                            )\n                        }}\n                    ></SpTextfield>\n\n                    <ul\n                        id=\"myMenu\"\n                        style={{\n                            // position: 'absolute',\n                            width: '100%',\n                            display: this.state.openMenu ? void 0 : 'none',\n                            zIndex: 1000,\n                        }}\n                    >\n                        {this.state.searchItems.map((item: string, index) => (\n                            <li\n                                key={index}\n                                title={item}\n                                onClick={() => {\n                                    console.log('onClick:')\n\n                                    this.setState({\n                                        searchQuery: item,\n                                        openMenu: false,\n                                    })\n                                    console.log(\n                                        'this.state.searchQuery: ',\n                                        this.state.searchQuery\n                                    )\n                                    console.log('item: ', item)\n                                    if (this.props.onChange) {\n                                        this.props.onChange(item)\n                                    }\n                                }}\n                                style={{ zIndex: 1000 }}\n                            >\n                                <a href=\"#\" style={{ fontSize: '12px' }}>\n                                    {item}\n                                </a>\n                            </li>\n                        ))}\n                    </ul>\n                </div>\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "typescripts/util/errorBoundary.tsx",
    "content": "import React, { Component, ErrorInfo, ReactNode } from 'react'\nimport { refreshUI } from '../sd_tab/util'\n\ninterface Props {\n    children: ReactNode\n}\n\ninterface State {\n    hasError: boolean\n    key: number\n}\ninterface State {\n    hasError: boolean\n    key: number\n}\n\nexport class ErrorBoundary extends Component<Props, State> {\n    public state: State = {\n        hasError: false,\n        key: 0,\n    }\n\n    public static getDerivedStateFromError(_: Error): Partial<State> {\n        // When an error occurs, we update state so the next render will show the fallback UI.\n        return { hasError: true }\n    }\n\n    public componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n        console.error('Uncaught error:', error, errorInfo)\n    }\n\n    handleRefresh = () => {\n        this.setState((prevState) => ({\n            hasError: false, // reset the error state\n            key: prevState.key + 1, // increment key to remount children\n        }))\n        // await refreshUI()\n    }\n\n    public render() {\n        if (this.state.hasError) {\n            return (\n                <div>\n                    <h1>Sorry.. there was an error</h1>\n                    <button onClick={this.handleRefresh}>Refresh</button>\n                </div>\n            )\n        }\n\n        // The key prop causes a remount of children when it changes\n        return <div key={this.state.key}>{this.props.children}</div>\n    }\n}\n"
  },
  {
    "path": "typescripts/util/grid.tsx",
    "content": "import React from 'react'\nimport { ActionButtonSVG, Thumbnail } from './elements'\n\nexport class Grid extends React.Component<{\n    // thumbnails_data?: any[]\n    thumbnails?: string[]\n    width?: number\n    height?: number\n    action_buttons?: any[]\n    children?: React.ReactNode\n    callback?: any\n    clicked_index?: number\n    permanent_indices?: number[]\n    thumbnails_styles?: string[]\n    fixedHeight?: boolean\n}> {\n    static defaultProps = {\n        width: 100,\n        height: 100,\n        thumbnails: [],\n        thumbnails_styles: [],\n        fixedHeight: false,\n    }\n\n    containerRef: React.RefObject<HTMLDivElement> = React.createRef()\n\n    componentDidMount() {\n        if (this.props.fixedHeight && this.containerRef.current) {\n            this.containerRef.current.style.height = `${this.containerRef.current.scrollHeight}px`\n        }\n    }\n\n    componentDidUpdate(prevProps: any) {\n        if (\n            this.props.fixedHeight !== prevProps.fixedHeight &&\n            this.containerRef.current\n        ) {\n            if (this.props.fixedHeight) {\n                this.containerRef.current.style.height = `${this.containerRef.current.scrollHeight}px`\n            } else {\n                this.containerRef.current.style.height = 'auto'\n            }\n        }\n    }\n    render() {\n        const img_style = {\n            width: `${this.props.width}px`,\n            // height: `${this.props.height}px`,\n            height: 'auto',\n        }\n        return (\n            <div className=\"viewer-container\" ref={this.containerRef}>\n                {this.props?.thumbnails?.map((thumbnail, index: number) => {\n                    // const thumbnail = this.props?.thumbnails\n                    // thumbnail\n                    //     ? this.props?.thumbnails[index]\n                    //     : 'https://source.unsplash.com/random'\n                    const thumbnail_class = this.props?.thumbnails_styles\n                        ? this.props?.thumbnails_styles[index]\n                        : ''\n                    return (\n                        <Thumbnail style={img_style} key={`thumbnail-${index}`}>\n                            <img\n                                style={img_style}\n                                onClick={async (event: any) => {\n                                    try {\n                                        console.log('image clicked')\n                                        if (this.props.callback) {\n                                            if (\n                                                this.props.callback.constructor\n                                                    .name === 'AsyncFunction'\n                                            ) {\n                                                await this.props?.callback(\n                                                    index,\n                                                    event\n                                                )\n                                            } else {\n                                                this.props?.callback(\n                                                    index,\n                                                    event\n                                                )\n                                            }\n                                        }\n                                    } catch (e) {\n                                        console.warn(\n                                            'error was thrown while calling a callback method'\n                                        )\n                                        console.warn(e)\n                                    }\n                                }}\n                                src={\n                                    thumbnail ??\n                                    'https://source.unsplash.com/random'\n                                }\n                                className={`viewer-image-container ${thumbnail_class}`}\n                            />\n\n                            {this.props?.action_buttons?.map((button, i) => {\n                                return (\n                                    i < 4 && (\n                                        <ActionButtonSVG\n                                            key={`action-button-${i}`}\n                                            ComponentType={button.ComponentType}\n                                            onClick={() => {\n                                                button.callback(index)\n                                            }}\n                                            title={button?.title}\n                                        ></ActionButtonSVG>\n                                    )\n                                )\n                            })}\n                        </Thumbnail>\n                    )\n                })}\n\n                {/* <div className=\"viewer-image-container\">\n                    {this.props?.children}\n                </div> */}\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "typescripts/util/logger.ts",
    "content": "import { format } from 'util'\nexport function formateLog(data: any, ...optional_param: any[]) {\n    const formattedOutput = format(data, ...optional_param)\n    return formattedOutput\n}\n"
  },
  {
    "path": "typescripts/util/oldSystem.tsx",
    "content": "import type Jimp from 'jimp'\n\n//@ts-ignore\nconst req = window['require']\n\n// because we use window['require'], so the base path of this require function is the root path of plugin.\nconst selection = req('./selection')\nconst note = req('./utility/notification')\nconst controlnet_preset = req('./utility/presets/controlnet_preset')\n\nconst Enum = req('./enum')\nconst api = req('./utility/api')\nconst python_replacement = req('./utility/sdapi/python_replacement')\nconst sdapi = req('./sdapi_py_re')\nconst html_manip = req('./utility/html_manip')\nconst psapi = req('./psapi')\nconst general = req('./utility/general')\nconst io = req('./utility/io')\nconst settings_tab = req('./utility/tab/settings')\nconst layer_util = req('./utility/layer')\nconst session = req('./utility/session')\nconst dialog_box = req('./dialog_box')\nconst sampler_data = req('./utility/sampler')\n\nconst thumbnail = req('./thumbnail')\ninterface _Jimp extends Jimp {}\nconst _Jimp: typeof Jimp = (window as any)['Jimp']\n\nexport {\n    selection,\n    note,\n    controlnet_preset,\n    Enum,\n    api,\n    python_replacement,\n    sdapi,\n    html_manip,\n    psapi,\n    general,\n    io,\n    settings_tab,\n    layer_util,\n    session,\n    dialog_box,\n    sampler_data,\n    thumbnail,\n    _Jimp as Jimp,\n}\n"
  },
  {
    "path": "typescripts/util/ts/api.ts",
    "content": "import { storage } from 'uxp'\n\ndeclare let g_sd_url: string\nexport async function requestGet(url: string) {\n    let data = null\n\n    const full_url = url\n    try {\n        let request = await fetch(full_url)\n        if (request.status === 404) {\n            return null\n        }\n\n        const contentType = request.headers.get('content-type')\n        if (contentType && contentType.includes('application/json')) {\n            data = await request.json()\n        } else if (\n            contentType &&\n            contentType.includes('application/octet-stream')\n        ) {\n            data = await request.arrayBuffer()\n        } else if (\n            contentType &&\n            (contentType.includes('image/jpeg') ||\n                contentType.includes('image/png'))\n        ) {\n            data = await request.arrayBuffer()\n        } else {\n            data = await request.text()\n        }\n\n        // console.log('data: ', data)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return data\n}\n\nexport async function requestPost(url: string, payload: any) {\n    let json = null\n\n    const full_url = url\n    try {\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n        })\n\n        if (request.status === 404) {\n            return null\n        }\n\n        json = await request.json()\n\n        // console.log('json: ', json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\nexport async function requestFormDataPost(url: string, payload: any) {\n    try {\n        var myHeaders = new Headers()\n        myHeaders.append('Cookie', 'PHPSESSID=n70fa2vmvm6tfmktf4jmstmd1i')\n\n        var formdata = new FormData()\n\n        for (const [key, value] of Object.entries(payload)) {\n            //@ts-ignore\n            formdata.append(key, value)\n        }\n        // formdata.append(\n        //     'source',\n        //     'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII='\n        // )\n        // formdata.append('key', '6d207e02198a847aa98d0a2a901485a5')\n\n        var requestOptions = {\n            method: 'POST',\n            headers: myHeaders,\n            body: formdata,\n            redirect: 'follow',\n        }\n\n        //@ts-ignore\n        const response = await fetch(url, requestOptions)\n        const result_json = response.json()\n        return result_json\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nexport async function isScriptInstalled(script_name: string): Promise<boolean> {\n    let is_installed = false\n    try {\n        const full_url = `${g_sd_url}/sdapi/v1/scripts`\n        const scripts = await requestGet(full_url)\n        is_installed =\n            scripts?.txt2img?.includes(script_name) ||\n            scripts?.img2img?.includes(script_name)\n    } catch (e) {\n        console.error(e)\n    }\n    console.log('is_installed: ', is_installed)\n    return is_installed\n}\n\nexport async function postArrayBuffer(url: string, data: Uint8Array) {\n    const response = await fetch(url, {\n        method: 'POST',\n        body: data,\n        headers: {\n            'Content-Type': 'application/octet-stream', // or whatever type your data should be\n        },\n    })\n\n    if (!response.ok) {\n        throw new Error('Network response was not ok')\n    }\n\n    return response.json() // parses JSON response into native JavaScript objects\n}\n\nexport async function postPng() {\n    const new_file = await storage.localFileSystem.getFileForOpening()\n    const arrayBuffer = await new_file.read({ format: storage.formats.binary })\n\n    //@ts-ignore\n    const extension_url = py_re.getExtensionUrl()\n    const full_url = `${extension_url}/readPngMetadata`\n    const json = await postArrayBuffer(full_url, new Uint8Array(arrayBuffer))\n    //@ts-ignore\n    // const json = await postArrayBuffer(full_url, 'ping')\n    console.log('json:', json)\n    return json\n}\n"
  },
  {
    "path": "typescripts/util/ts/document.ts",
    "content": "import { app, core, action } from 'photoshop'\nimport { Jimp, layer_util, psapi } from '../oldSystem'\nimport { storage } from 'uxp'\nimport { Layer } from 'photoshop/dom/Layer'\nimport { changeDpiDataUrl } from 'changedpi'\n\nconst executeAsModal = core.executeAsModal\nconst batchPlay = action.batchPlay\n\nenum DocumentTypeEnum {\n    NoBackground = 'no_background',\n    ImageBackground = 'image_background',\n    SolidBackground = 'solid_background',\n    ArtBoard = 'artboard',\n}\n\nasync function isCorrectBackground() {\n    const historylist = app.activeDocument.historyStates.filter(\n        (h) => h.name === 'Correct Background'\n    )\n    console.log('historylist:', historylist)\n    const is_correct_background = historylist.length > 0 ? true : false\n    return is_correct_background\n}\n\nasync function getColor(X: any, Y: any) {\n    // const background_layer_id = await app.activeDocument.backgroundLayer.id\n\n    try {\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'colorSampler',\n                    _target: {\n                        _ref: 'document',\n                        _enum: 'ordinal',\n                        _value: 'targetEnum',\n                    },\n                    samplePoint: {\n                        horizontal: X,\n                        vertical: Y,\n                    },\n                },\n            ],\n            {}\n        )\n\n        const red = result[0].colorSampler.red\n        const green = result[0].colorSampler.grain\n        const blue = result[0].colorSampler.blue\n\n        return [red, green, blue]\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//REFACTOR: move to document.js\nasync function findDocumentType() {\n    //check if the background layer exsit\n    //if it doesn't return false\n    //if it does:\n    //duplicate the background layer and place it on the top of the document.\n    //sampler 10 random pixles\n    //and check if all the pixels has the same values.\n    //if it doesn't duplicate the background layer and place it above the background layer.\n    // make a white background layer.\n    //return true\n\n    let document_type\n    const background_layer = await app.activeDocument.backgroundLayer\n    const has_background_layer = app.activeDocument.backgroundLayer\n        ? true\n        : false\n    const artboards = Array.from(await app.activeDocument.artboards)\n    if (artboards.length > 0) {\n        document_type = DocumentTypeEnum['ArtBoard']\n        // } else if (layer_util.Layer.doesLayerExist(background_layer)) {\n    } else if (has_background_layer) {\n        //assume it's solid white background if correctHistory > 1 || layers.length > 5\n        const b_correct_background = await isCorrectBackground() // check the history for correct operation\n        if (b_correct_background) {\n            document_type = DocumentTypeEnum['SolidBackground']\n        } else {\n            //else\n\n            //background layer does exist\n            //check if it's solid color background or an image background\n            //sampler 10 random pixels\n            let width = app.activeDocument.width\n            let height = app.activeDocument.height\n            let old_rgb: any\n            let same_color = true\n\n            await executeAsModal(\n                async () => {\n                    if (app.activeDocument.layers.length > 1) {\n                        await layer_util.toggleBackgroundLayerExe() // hide all layers except the background layer\n                    }\n                    for (let i = 0; i < 10; ++i) {\n                        let x = Math.floor(Math.random() * width)\n                        let y = Math.floor(Math.random() * height)\n\n                        const rgb = (await getColor(x, y))!\n                        if (old_rgb) {\n                            if (\n                                Math.round(old_rgb[0]) === Math.round(rgb[0]) &&\n                                Math.round(old_rgb[1]) === Math.round(rgb[1]) &&\n                                Math.round(old_rgb[2]) === Math.round(rgb[2])\n                            ) {\n                            } else {\n                                same_color = false //it's an image background\n                                break\n                            }\n                        }\n                        old_rgb = rgb\n                    }\n                    if (app.activeDocument.layers.length > 1) {\n                        await layer_util.toggleBackgroundLayerExe() // undo the toggle operation; display all layers\n                    }\n                },\n                {\n                    commandName: 'Checking Document Type...',\n                }\n            )\n\n            document_type = same_color\n                ? DocumentTypeEnum['SolidBackground']\n                : DocumentTypeEnum['ImageBackground']\n        }\n    } else {\n        //create the background layer since it doesn't exsit\n        document_type = DocumentTypeEnum['NoBackground']\n    }\n\n    return document_type\n}\n\nasync function correctDocumentType(documentType: any) {\n    if (documentType === DocumentTypeEnum['SolidBackground']) {\n        //do nothing\n    } else if (documentType === DocumentTypeEnum['ImageBackground']) {\n        //duplicate the layer\n        await executeAsModal(\n            async () => {\n                const image_layer: any =\n                    await app.activeDocument.backgroundLayer!.duplicate() //\n                image_layer.name = 'Image'\n                await app.activeDocument.backgroundLayer!.delete()\n                await layer_util.createBackgroundLayer(255, 255, 255)\n            },\n            {\n                commandName: 'Correct Background',\n            }\n        )\n    } else if (documentType === DocumentTypeEnum['ArtBoard']) {\n        //duplicate the layer\n        await app.showAlert(\n            \"the plugin doesn't work with artboards, create normal document with no artboard to use the plugin\"\n        )\n        throw \"the plugin doesn't work with artboards, create normal document with no artboard to use the plugin\"\n    } else if (documentType === DocumentTypeEnum['NoBackground']) {\n        await layer_util.createBackgroundLayer(255, 255, 255)\n    }\n}\n\nexport async function initializeBackground() {\n    await executeAsModal(\n        async (context) => {\n            const document_type = await findDocumentType()\n\n            const history_id = await context.hostControl.suspendHistory({\n                documentID: app.activeDocument.id, //TODO: change this to the session document id\n                name: 'Correct Background',\n            })\n            //store selection\n            //store active layer\n            const selectionInfo = await psapi.getSelectionInfoExe()\n            await psapi.unSelectMarqueeExe()\n            const active_layers = app.activeDocument.activeLayers\n\n            //1)check if the documnet has a background layer\n\n            await correctDocumentType(document_type)\n\n            //retore selection\n            //restore active layer\n            await psapi.reSelectMarqueeExe(selectionInfo)\n            await psapi.selectLayersExe(active_layers)\n            await context.hostControl.resumeHistory(history_id)\n        },\n        {\n            commandName: 'Initialize Background',\n        }\n    )\n}\n\n/**\n * transfer a base64image to a layer.\n * the image will located at the top-left corner of canvas.\n * @param b64Image\n * @param options\n * @returns\n */\nexport async function base64ToFileAndGetLayer(\n    b64Image: string,\n    options: {\n        image_name?: string\n    } = {}\n): Promise<{ layer: Layer; width: number; height: number }> {\n    const imageName = options.image_name || 'output_image.png'\n\n    b64Image = changeDpiDataUrl(\n        'data:image/png;base64,' + b64Image,\n        app.activeDocument.resolution\n    )\n    const img = Buffer.from(b64Image.split(',')[1], 'base64')\n    const jimp_image = await Jimp.read(img)\n\n    const folder = await storage.localFileSystem.getTemporaryFolder()\n    const file = await folder.createFile(imageName + '.png', {\n        overwrite: true,\n    })\n\n    await file.write(img.buffer, { format: storage.formats.binary })\n\n    const token = await storage.localFileSystem.createSessionToken(file) // batchPlay requires a token on _path\n\n    const selection_info = await psapi.getSelectionInfoExe()\n\n    let imported_layer\n    let willScaleSize = Math.min(\n        1,\n        app.activeDocument.width / jimp_image.bitmap.width,\n        app.activeDocument.height / jimp_image.bitmap.height\n    )\n\n    await executeAsModal(\n        () =>\n            batchPlay(\n                [\n                    {\n                        _obj: 'set',\n                        _target: [\n                            {\n                                _property: 'selection',\n                                _ref: 'channel',\n                            },\n                        ],\n                        to: {\n                            _obj: 'rectangle',\n                            bottom: {\n                                _unit: 'pixelsUnit',\n                                _value:\n                                    jimp_image.bitmap.height * willScaleSize,\n                            },\n                            left: {\n                                _unit: 'pixelsUnit',\n                                _value: 0.0,\n                            },\n                            right: {\n                                _unit: 'pixelsUnit',\n                                _value: jimp_image.bitmap.width * willScaleSize,\n                            },\n                            top: {\n                                _unit: 'pixelsUnit',\n                                _value: 0.0,\n                            },\n                        },\n                    },\n                ],\n                {}\n            ),\n        {\n            commandName: 'select import area',\n        }\n    )\n\n    await executeAsModal(\n        async () => {\n            const result = await batchPlay(\n                [\n                    {\n                        _obj: 'placeEvent',\n                        // ID: 6,\n                        null: {\n                            _path: token,\n                            _kind: 'local',\n                        },\n                        freeTransformCenterState: {\n                            _enum: 'quadCenterState',\n                            _value: 'QCSCorner0',\n                        },\n                        offset: {\n                            _obj: 'offset',\n                            horizontal: { _unit: 'pixelsUnit', _value: 0.0 },\n                            vertical: { _unit: 'pixelsUnit', _value: 0.0 },\n                        },\n                        _isCommand: true,\n                        _options: {\n                            dialogOptions: 'dontDisplay',\n                        },\n                        width: {\n                            _unit: 'percentUnit',\n                            _value: (1 / willScaleSize) * 100,\n                        },\n                        height: {\n                            _unit: 'percentUnit',\n                            _value: (1 / willScaleSize) * 100,\n                        },\n                    },\n                ],\n                {}\n            )\n            console.log('placeEmbedd batchPlay result: ', result)\n\n            imported_layer = await app.activeDocument.activeLayers[0]\n        },\n        {\n            commandName: 'import base64',\n        }\n    )\n\n    await psapi.reSelectMarqueeExe(selection_info)\n    if (!imported_layer) {\n        throw new Error('base64ToFileAndGetLayer failed: layer is empty')\n    }\n    return {\n        layer: imported_layer,\n        height: jimp_image.bitmap.height,\n        width: jimp_image.bitmap.width,\n    }\n}\n"
  },
  {
    "path": "typescripts/util/ts/enum.ts",
    "content": "export enum GenerationModeEnum {\n    Txt2Img = 'txt2img',\n    Img2Img = 'img2img',\n    Inpaint = 'inpaint',\n    Outpaint = 'outpaint',\n    Upscale = 'upscale',\n    LassoInpaint = 'lasso_inpaint',\n    LassoOutpaint = 'lasso_outpaint',\n}\n\nexport enum ScriptMode {\n    Txt2Img = 'txt2img',\n    Img2Img = 'img2img',\n    Inpaint = 'inpaint',\n    Outpaint = 'outpaint',\n}\n\nexport enum MaskModeEnum {\n    Transparent = 'transparent',\n    Borders = 'border',\n    Corners = 'corner',\n}\n\nexport interface SelectionInfoType {\n    left: number\n    right: number\n    top: number\n    bottom: number\n    width: number\n    height: number\n}\n\nexport enum PresetTypeEnum {\n    SDPreset = 'sd_preset',\n    ControlNetPreset = 'controlnet_preset',\n}\n"
  },
  {
    "path": "typescripts/util/ts/general.ts",
    "content": "import { app, core, imaging } from 'photoshop'\nimport { io, psapi } from '../oldSystem'\nimport { host } from 'uxp'\n\nexport function autoResize(textarea: any, text_content: string, delay = 300) {\n    try {\n        let g_style_timeout: any\n        const measure_id = `measure-${textarea.id}`\n        let measure = document.getElementById('measure')!\n        if (!measure) {\n            measure = document.createElement('div')\n            measure.setAttribute('id', measure_id)\n            measure.style.visibility = 'hidden'\n            measure.style.whiteSpace = 'pre-wrap'\n            measure.style.position = 'absolute'\n            measure.style.fontSize = '14px'\n            document.body.appendChild(measure)\n        }\n        measure.style.width = textarea.offsetWidth + 'px'\n        measure.textContent = text_content\n\n        let checkCount = 0\n        const checkHeight = () => {\n            if (measure.offsetHeight > 0 || checkCount >= 50) {\n                clearTimeout(g_style_timeout)\n                g_style_timeout = setTimeout(() => {\n                    console.log('textarea id: ', textarea.id)\n                    let height = measure.offsetHeight\n                    height = Math.max(100, height)\n                    height = Math.min(450, height)\n                    textarea.style.height = height + 'px'\n                    console.log('height: ', height)\n                }, delay)\n            } else {\n                checkCount++\n                setTimeout(checkHeight, delay)\n            }\n        }\n        checkHeight()\n    } catch (e) {\n        console.warn(\n            'failed to autoResize()',\n            textarea.id,\n            text_content,\n            delay,\n            e\n        )\n    }\n}\n\nexport async function urlToCanvas(url: string, image_name = 'image.png') {\n    await io.IO.urlToLayer(url, image_name)\n}\n\nexport const copyJson = (originalObject: any) =>\n    JSON.parse(JSON.stringify(originalObject))\n\nexport function base64ToBase64Url(base64_image: string) {\n    return 'data:image/png;base64,' + base64_image\n}\nexport function base64UrlToBase64(base64_url: string) {\n    const base64 = base64_url.replace(/data:image\\/.*;base64,/, '')\n    return base64\n}\n\nexport function newOutputImageName(format = 'png') {\n    const random_id = Math.floor(Math.random() * 100000000000 + 1) // Date.now() doesn't have enough resolution to avoid duplicate\n    const image_name = `output- ${Date.now()}-${random_id}.${format}`\n    console.log('generated image name:', image_name)\n    return image_name\n}\n\nexport function isValidVersion(minMajorVersion: number) {\n    const current_major_version = host.version.split('.')[0]\n    if (parseInt(current_major_version) >= minMajorVersion) {\n        return true\n    } else {\n        return false\n    }\n}\n\nasync function getImageFromLayer(\n    sourceBounds: any,\n    layer_id: number | undefined,\n    components: any\n) {\n    const image_obj = await imaging.getPixels({\n        ...(sourceBounds && {\n            sourceBounds: {\n                left: sourceBounds.left,\n                top: sourceBounds.top,\n                right: sourceBounds.right,\n                bottom: sourceBounds.bottom,\n            },\n        }),\n        ...(layer_id && { layerID: layer_id }),\n        components: components,\n        applyAlpha: true,\n        colorSpace: 'RGB',\n    })\n\n    return image_obj\n}\n\nasync function imageObjectToBase64(imgObj: any) {\n    const pixelData = await imgObj.imageData.getData()\n    // const base64 = Buffer.from(pixelData).toString('base64')\n    // const base64 = _arrayBufferToBase64(pixelData)\n    const jpegData = await imaging.encodeImageData({\n        imageData: imgObj.imageData,\n        base64: true,\n        // pixelFormat: 'RGBA',\n        // applyAlpha: true,\n    })\n    return jpegData\n    // return base64\n}\n\nasync function imageObjectToBase64Url(imgObj: any) {\n    const jpegData = await imageObjectToBase64(imgObj)\n    const dataUrl = 'data:image/jpeg;base64,' + jpegData\n    // const dataUrl = 'data:image/png;base64,' + jpegData\n\n    return dataUrl\n}\n\nexport async function getImageFromCanvas_new(layer_id?: number) {\n    let data_url\n    if (!isValidVersion(25)) {\n        const errorMessage = `Real-time img2img Require Adobe Photoshop version 25 or higher. Your current version is ${host.version}. Please update Adobe Photoshop to use this feature. You can still use realtime txt2img.`\n        // app.showAlert(errorMessage)\n        throw errorMessage\n    }\n    await core.executeAsModal(\n        async () => {\n            const selection_info = await psapi.getSelectionInfoExe()\n            // let imgObj = await getImageFromLayer({},app.activeDocument.activeLayers[0].id,3)\n            let imgObj = await getImageFromLayer(selection_info, layer_id, 3)\n\n            data_url = await imageObjectToBase64Url(imgObj)\n            // console.log('data_url:', data_url)\n            // html_manip.setInitImageSrc(data_url)\n            console.log('getImageFromCanvas: triggered')\n        },\n        { commandName: 'Get  Image from Canvas' }\n    )\n    return data_url\n}\n\nexport function deleteKeys(obj: Record<string, any>, keys: string[]) {\n    keys.forEach((key) => {\n        if (obj.hasOwnProperty(key)) {\n            delete obj[key]\n        }\n    })\n    return obj\n}\n"
  },
  {
    "path": "typescripts/util/ts/io.ts",
    "content": "import { app, core, action } from 'photoshop'\nimport { Jimp, io, psapi } from '../oldSystem'\nimport { base64ToFileAndGetLayer } from './document'\nimport { transformCurrentLayerTo } from './layer'\nimport { Layer } from 'photoshop/dom/Layer'\nimport { lstatSync, readFileSync, writeFileSync } from 'fs'\nimport { AStore } from '../../main/astore'\nimport { constants } from 'photoshop'\nconst { RasterizeType } = constants\n\nconst executeAsModal = core.executeAsModal\ntype KeyValuePair = { [key: string]: any }\n\n//REFACTOR: move to psapi.js\nexport function _arrayBufferToBase64(buffer: any) {\n    var binary = ''\n    var bytes = new Uint8Array(buffer)\n    var len = bytes.byteLength\n    for (var i = 0; i < len; i++) {\n        binary += String.fromCharCode(bytes[i])\n    }\n    return window.btoa(binary)\n}\n\nexport async function moveImageToLayer_old(\n    base64_image: string,\n    selection_info: any,\n    layer_name: string = 'output_image.png'\n) {\n    let layer\n    try {\n        const to_x = selection_info?.left\n        const to_y = selection_info?.top\n        const width = selection_info?.width\n        const height = selection_info?.height\n        layer = await io.IO.base64ToLayer(\n            base64_image,\n            layer_name,\n            to_x,\n            to_y,\n            width,\n            height\n        )\n    } catch (e) {\n        console.warn(e)\n        layer = null\n    }\n    return layer\n}\nexport async function moveImageToLayer(\n    base64_image: string,\n    selection_info: any,\n    layer_name: string = 'output_image.png',\n    as_smart_object: boolean = true\n): Promise<Layer> {\n    if (!base64_image) throw new Error('moveImageToLayer: image is empty')\n    let layer: Layer | null\n    try {\n        const to_x = selection_info?.left\n        const to_y = selection_info?.top\n        const width = selection_info?.width\n        const height = selection_info?.height\n\n        const res = await base64ToFileAndGetLayer(base64_image, {\n            image_name: layer_name,\n        })\n        layer = res.layer\n\n        await psapi.setVisibleExe(layer, true)\n        await transformCurrentLayerTo(\n            {\n                left: to_x,\n                top: to_y,\n                width,\n                height,\n            },\n            {\n                width: res.width,\n                height: res.height,\n                left: 0,\n                top: 0,\n            }\n        )\n        await psapi.setVisibleExe(layer, true)\n\n        if (as_smart_object === false) {\n            await executeAsModal(\n                async () => {\n                    if (layer) await layer.rasterize(RasterizeType.ENTIRELAYER) //rastrize the layer\n                },\n                { commandName: 'rasterized the layer' }\n            )\n        }\n    } catch (e) {\n        console.warn(e)\n        layer = null\n    }\n    if (!layer) {\n        throw new Error('moveImageToLayer failed: layer is empty')\n    }\n    return layer\n}\n\nexport async function convertGrayscaleToWhiteAndTransparent(\n    base64: string\n): Promise<{\n    base64: string\n    width: number\n    height: number\n}> {\n    function grayToWhiteAndTransparent(\n        this: Jimp,\n        x: number,\n        y: number,\n        idx: number\n    ) {\n        let color\n        if (\n            this.bitmap.data[idx] !== 0 &&\n            this.bitmap.data[idx + 1] !== 0 &&\n            this.bitmap.data[idx + 2] !== 0\n        ) {\n            color = 0xffffffff\n        } else {\n            color = 0x00000000\n        }\n        this.setPixelColor(color, x, y)\n    }\n    try {\n        const jimp_image = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        const jimp_mask = await jimp_image.scan(\n            0,\n            0,\n            jimp_image.bitmap.width,\n            jimp_image.bitmap.height,\n            grayToWhiteAndTransparent\n        )\n\n        const base64_monochrome_mask = await getBase64FromJimp(jimp_mask)\n\n        return {\n            base64: base64_monochrome_mask,\n            height: jimp_image.bitmap.height,\n            width: jimp_image.bitmap.width,\n        }\n    } catch (e) {\n        console.warn(e)\n        throw e\n    }\n}\n\nasync function getBase64FromJimp(jimp_image: Jimp) {\n    const dataURL = await jimp_image.getBase64Async(Jimp.MIME_PNG)\n    const base64 = dataURL.replace(/^data:image\\/png;base64,/, '')\n    return base64\n}\n\nexport function readPreset(path: string) {\n    try {\n        const content = readFileSync(path, 'utf-8')\n        JSON.parse(content)\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport function writePreset(path: string, preset: KeyValuePair) {\n    try {\n        writeFileSync(path, JSON.stringify(preset))\n    } catch (e) {\n        console.error(e)\n    }\n}\n\nexport function storeToPreset(store: any) {\n    return store.toJsFunc().data\n}\n\nexport function presetToStore(preset: KeyValuePair, store: any) {\n    store.data = {\n        ...store.data,\n        ...preset,\n    }\n}\n"
  },
  {
    "path": "typescripts/util/ts/layer.ts",
    "content": "import { app, core, action } from 'photoshop'\nimport { layer_util, psapi } from '../oldSystem'\n// import { settings_tab_ts } from '../../entry'\nimport * as settings_tab_ts from '../../settings/settings'\nconst executeAsModal = core.executeAsModal\nconst { batchPlay } = action\n\nexport interface RectArea {\n    top: number\n    left: number\n    height: number\n    width: number\n}\n\nasync function transformBatchPlay(\n    centerX: number,\n    centerY: number,\n    scaleRatioX: number,\n    scaleRatioY: number,\n    translateX: number,\n    translateY: number\n) {\n    const setInterpolationMethodDesc = {\n        _obj: 'set',\n        _target: [\n            {\n                _ref: 'property',\n                _property: 'generalPreferences',\n            },\n            {\n                _ref: 'application',\n                _enum: 'ordinal',\n                _value: 'targetEnum',\n            },\n        ],\n        to: {\n            _obj: 'generalPreferences',\n            interpolationMethod: {\n                _enum: 'interpolationType',\n                // _value: 'bilinear',\n                _value: settings_tab_ts.store.data.scale_interpolation_method\n                    .photoshop,\n            },\n        },\n        _isCommand: true,\n    }\n\n    let imageSizeDescriptor = {\n        _obj: 'transform',\n        _target: [\n            {\n                _ref: 'layer',\n                _enum: 'ordinal',\n                _value: 'targetEnum',\n            },\n        ],\n        freeTransformCenterState: {\n            _enum: 'quadCenterState',\n            _value: 'QCSIndependent',\n        },\n        position: {\n            _obj: 'paint',\n            horizontal: { _unit: 'pixelsUnit', _value: centerX },\n            vertical: { _unit: 'pixelsUnit', _value: centerY },\n        },\n        offset: {\n            _obj: 'offset',\n            horizontal: {\n                _unit: 'pixelsUnit',\n                _value: translateX,\n            },\n            vertical: {\n                _unit: 'pixelsUnit',\n                _value: translateY,\n            },\n        },\n        width: {\n            _unit: 'percentUnit',\n            _value: scaleRatioX,\n        },\n        height: {\n            _unit: 'percentUnit',\n            _value: scaleRatioY,\n        },\n        linked: true,\n        interfaceIconFrameDimmed: {\n            _enum: 'interpolationType',\n            // _value: 'bilinear',\n            _value: settings_tab_ts.store.data.scale_interpolation_method\n                .photoshop,\n        },\n        _isCommand: true,\n    }\n    return batchPlay([setInterpolationMethodDesc, imageSizeDescriptor], {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n}\n\nexport async function transformCurrentLayerTo(\n    toRect: RectArea,\n    fromRect: RectArea\n) {\n    const selection_info = await psapi.getSelectionInfoExe()\n    await psapi.unSelectMarqueeExe()\n\n    const scale_x_ratio = (toRect.width / fromRect.width) * 100\n    const scale_y_ratio = (toRect.height / fromRect.height) * 100\n\n    const top_dist = toRect.top - fromRect.top\n    const left_dist = toRect.left - fromRect.left\n    console.log(\n        'transformCurrentLayer',\n        top_dist,\n        left_dist,\n        scale_x_ratio,\n        scale_y_ratio\n    )\n\n    await executeAsModal(\n        () =>\n            transformBatchPlay(\n                fromRect.left,\n                fromRect.top,\n                scale_x_ratio,\n                scale_y_ratio,\n                left_dist,\n                top_dist\n            ),\n        { commandName: 'transform' }\n    )\n\n    await psapi.reSelectMarqueeExe(selection_info)\n}\n\nexport async function SetLayerColor() {\n    let result\n\n    let command = [\n        {\n            _obj: 'set',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n            to: { _obj: 'layer', color: { _enum: 'color', _value: 'red' } },\n        },\n    ]\n    result = await batchPlay(command, {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n}\n"
  },
  {
    "path": "typescripts/util/ts/sdapi.ts",
    "content": "declare let g_version: any\ndeclare let g_sd_url: any\n\nexport async function getVersionRequest() {\n    console.log('requestGetSamplers: ')\n    const current_version = g_version\n\n    return current_version\n}\nexport async function requestGetSamplers() {\n    let json = null\n    try {\n        console.log('requestGetSamplers: ')\n\n        const full_url = `${g_sd_url}/sdapi/v1/samplers`\n        let request = await fetch(full_url)\n        json = await request.json()\n        // console.log('samplers json:', json)\n    } catch (e) {\n        console.warn(e)\n    }\n    return json\n}\n\nexport async function requestGetUpscalers() {\n    console.log('requestGetUpscalers: ')\n    let json = []\n    const full_url = `${g_sd_url}/sdapi/v1/upscalers`\n    try {\n        let request = await fetch(full_url)\n        json = await request.json()\n        console.log('upscalers json:')\n        console.dir(json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\n\nexport async function setInpaintMaskWeight(value: number) {\n    const full_url = `${g_sd_url}/sdapi/v1/options`\n    try {\n        const payload = {\n            inpainting_mask_weight: value,\n        }\n        await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nexport async function requestGetModels() {\n    console.log('requestGetModels: ')\n    let json = []\n    const full_url = `${g_sd_url}/sdapi/v1/sd-models`\n    try {\n        let res = await fetch(full_url)\n        if (res.status == 200) {\n            json = await res.json()\n        }\n        console.log('models json:')\n        console.dir(json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\n\nexport async function requestSwapModel(model_title: string) {\n    console.log('requestSwapModel: ')\n\n    const full_url = `${g_sd_url}/sdapi/v1/options`\n    const payload = {\n        sd_model_checkpoint: model_title,\n    }\n    let request = await fetch(full_url, {\n        method: 'POST',\n        headers: {\n            Accept: 'application/json',\n            'Content-Type': 'application/json',\n        },\n        body: JSON.stringify(payload),\n    })\n\n    let json = await request.json()\n\n    console.log('models json:')\n    console.dir(json)\n\n    return json\n}\n"
  },
  {
    "path": "typescripts/util/ts/selection.ts",
    "content": "import { moveImageToLayer, moveImageToLayer_old } from './io'\nimport { io, layer_util, psapi } from '../oldSystem'\n\nimport { action, core } from 'photoshop'\nimport { MaskModeEnum } from './enum'\nimport { session_store } from '../../stores'\nconst executeAsModal = core.executeAsModal\nconst batchPlay = action.batchPlay\n\nexport async function applyMaskFromBlackAndWhiteImage(\n    black_and_white_base64: string,\n    layer_id: any,\n    selectionInfo: any,\n    b_borders_or_corners: MaskModeEnum = MaskModeEnum.Transparent,\n    expand_by = 10\n) {\n    let mask_layer\n    try {\n        const transparent_mask_base64 =\n            await io.convertBlackToTransparentKeepBorders(\n                black_and_white_base64,\n                b_borders_or_corners\n            )\n        mask_layer = await moveImageToLayer(\n            transparent_mask_base64,\n            selectionInfo\n        )\n\n        let cmd = [\n            {\n                _obj: 'select',\n                _target: [{ _id: mask_layer.id, _ref: 'layer' }],\n                makeVisible: false,\n            },\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _ref: 'channel',\n                    _enum: 'channel',\n                    _value: 'transparencyEnum',\n                },\n                _isCommand: true,\n            },\n            {\n                _obj: 'expand',\n                by: {\n                    _unit: 'pixelsUnit',\n                    _value: expand_by,\n                },\n                selectionModifyEffectAtCanvasBounds: true,\n                _isCommand: true,\n            },\n            {\n                _obj: 'select',\n                _target: [{ _id: layer_id, _ref: 'layer' }],\n\n                makeVisible: false,\n            },\n            {\n                _obj: 'make',\n                new: {\n                    _class: 'channel',\n                },\n                at: {\n                    _ref: 'channel',\n                    _enum: 'channel',\n                    _value: 'mask',\n                },\n                using: {\n                    _enum: 'userMaskEnabled',\n                    _value: 'revealSelection',\n                },\n                _isCommand: true,\n            },\n        ]\n        //@ts-ignore\n        // await timer(g_timer_value)\n        await executeAsModal(\n            async () => {\n                const result = await batchPlay(cmd, {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                })\n            },\n            {\n                commandName: 'select opaque pixels',\n            }\n        )\n    } catch (e) {\n        console.error(e)\n    } finally {\n        await layer_util.deleteLayers([mask_layer])\n    }\n}\n\nexport async function selectionFromBlackAndWhiteImage(\n    black_and_white_base64: string,\n    selectionInfo: any,\n    b_borders_or_corners: MaskModeEnum = MaskModeEnum.Transparent\n) {\n    let mask_layer\n    try {\n        const transparent_mask_base64 =\n            await io.convertBlackToTransparentKeepBorders(\n                black_and_white_base64,\n                b_borders_or_corners\n            )\n        mask_layer = await moveImageToLayer(\n            transparent_mask_base64,\n            selectionInfo\n        )\n\n        let cmd = [\n            {\n                _obj: 'select',\n                _target: [{ _id: mask_layer.id, _ref: 'layer' }],\n                makeVisible: false,\n            },\n            {\n                _obj: 'set',\n                _target: [\n                    {\n                        _ref: 'channel',\n                        _property: 'selection',\n                    },\n                ],\n                to: {\n                    _ref: 'channel',\n                    _enum: 'channel',\n                    _value: 'transparencyEnum',\n                },\n                _isCommand: true,\n            },\n        ]\n        //@ts-ignore\n        // await timer(g_timer_value)\n        await executeAsModal(\n            async () => {\n                const result = await batchPlay(cmd, {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                })\n            },\n            {\n                commandName: 'select opaque pixels',\n            }\n        )\n    } catch (e) {\n        console.error(e)\n    } finally {\n        await layer_util.deleteLayers([mask_layer])\n    }\n}\n\nexport async function activateSessionSelectionArea() {\n    try {\n        if (psapi.isSelectionValid(session_store.data.selectionInfo)) {\n            await psapi.reSelectMarqueeExe(session_store.data.selectionInfo)\n            //@ts-ignore\n            await eventHandler()\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n"
  },
  {
    "path": "typescripts/util/ts/ui_ts.ts",
    "content": "import { multiPrompts } from '../../entry'\nimport {\n    getAllCustomPresetsSettings,\n    loadCustomPreset,\n    loadPreset,\n} from '../../preset/shared_ui_preset'\nimport { sd_tab_store } from '../../stores'\nimport { html_manip } from '../oldSystem'\nimport { PresetTypeEnum, ScriptMode } from './enum'\n\nlet LatentNoiseSettings = {\n    model: null,\n    prompt_shortcut: null,\n    positive_prompt: null,\n    negative_prompt: null,\n    generation_mode: null,\n    batch_size: null,\n    steps: null,\n    width: null,\n    height: null,\n    firstphase_width: null,\n    firstphase_height: null,\n    cfg: null,\n    denoising_strength: 0.92,\n    hi_res_denoising_strength: null,\n    mask_blur: null,\n    inpaint_at_full_res: null,\n    hi_res_fix: null,\n    inpaint_padding: null,\n    seed: null,\n    samplers: null,\n    mask_content: '2',\n}\n\nlet FillSettings = {\n    model: null,\n    prompt_shortcut: null,\n    positive_prompt: null,\n    negative_prompt: null,\n    generation_mode: null,\n    batch_size: null,\n    steps: null,\n    width: null,\n    height: null,\n    firstphase_width: null,\n    firstphase_height: null,\n    cfg: null,\n    denoising_strength: 0.7,\n    hi_res_denoising_strength: null,\n    mask_blur: null,\n    inpaint_at_full_res: null,\n    hi_res_fix: null,\n    inpaint_padding: null,\n    seed: null,\n    samplers: null,\n    mask_content: '0',\n}\nlet OriginalSettings = {\n    model: null,\n    prompt_shortcut: null,\n    positive_prompt: null,\n    negative_prompt: null,\n    generation_mode: null,\n    batch_size: null,\n    steps: null,\n    width: null,\n    height: null,\n    firstphase_width: null,\n    firstphase_height: null,\n    cfg: null,\n    denoising_strength: 0.7,\n    hi_res_denoising_strength: null,\n    mask_blur: null,\n    inpaint_at_full_res: null,\n    hi_res_fix: null,\n    inpaint_padding: null,\n    seed: null,\n    samplers: null,\n    mask_content: '1',\n}\nlet HealBrushSettings = {\n    model: null,\n    prompt_shortcut: null,\n    positive_prompt: null,\n    negative_prompt: null,\n    generation_mode: null,\n    batch_size: null,\n    steps: '25',\n    width: null,\n    height: null,\n    firstphase_width: null,\n    firstphase_height: null,\n    cfg: '9',\n    denoising_strength: 0.92,\n    hi_res_denoising_strength: null,\n    mask_blur: 1,\n    inpaint_at_full_res: null,\n    hi_res_fix: null,\n    inpaint_padding: null,\n    seed: null,\n    samplers: null,\n    mask_content: '2',\n    mask_expansion: 2,\n}\n\nclass UI {\n    constructor() {}\n}\ninterface UIElements {\n    [key: string]: UIElement\n\n    prompt: UIElement\n    negative_prompt: UIElement\n    mode: UIElement\n    batch_size: UIElement\n    batch_count: UIElement\n\n    steps: UIElement\n    width: UIElement\n    height: UIElement\n\n    cfg: UIElement\n    denoising_strength: UIElement\n    mask_content: UIElement\n    seed: UIElement\n    mask_blur: UIElement\n    mask_expansion: UIElement\n    samplers: UIElement\n}\nclass UIElement {\n    name: any\n    html_elem: any\n    sd_value: any\n    constructor() {\n        this.name\n        this.html_elem\n        this.sd_value\n    }\n    setValue(new_value: any) {}\n    getValue(): any {}\n}\nfunction createUIElement(getter: any, setter: any) {\n    let ui_element_obj = new UIElement()\n    ui_element_obj.getValue = getter\n    ui_element_obj.setValue = setter\n    return ui_element_obj\n}\nclass UISettings {\n    prompt: UIElement\n    negative_prompt: UIElement\n    mode: UIElement\n    steps: UIElement\n    batch_size: UIElement\n    batch_count: UIElement\n    width: UIElement\n    height: UIElement\n    cfg: UIElement\n    denoising_strength: UIElement\n    mask_content: UIElement\n    seed: UIElement\n    mask_blur: UIElement\n    mask_expansion: UIElement\n    samplers: UIElement\n    uiElements: UIElements\n    // get and set the settings of the ui. the stable diffusion settings not the human friendly settings\n    constructor() {\n        const createUIElementWrapper = <T extends never>(\n            getter: () => T,\n            setter: (value: T) => void\n        ) => {\n            return createUIElement(getter, setter)\n        }\n\n        const sdTabStoreDataWrapper = <T extends never>(\n            key: keyof typeof sd_tab_store.data\n        ) => {\n            return createUIElementWrapper(\n                () => sd_tab_store.data[key] as T,\n                (value: T) => (sd_tab_store.data[key] = value)\n            )\n        }\n        this.prompt = createUIElement(\n            () => {\n                return multiPrompts.getPrompt().positive\n            },\n            (value: string) => {\n                multiPrompts.setPrompt({ positive: value })\n            }\n        )\n        this.negative_prompt = createUIElement(\n            () => {\n                return multiPrompts.getPrompt().negative\n            },\n            (value: string) => {\n                multiPrompts.setPrompt({ negative: value })\n            }\n        )\n\n        this.mode = sdTabStoreDataWrapper('rb_mode')\n        this.batch_size = sdTabStoreDataWrapper('batch_size')\n        this.batch_count = sdTabStoreDataWrapper('batch_count')\n        this.steps = sdTabStoreDataWrapper('steps')\n        this.width = sdTabStoreDataWrapper('width')\n        this.height = sdTabStoreDataWrapper('height')\n        this.cfg = sdTabStoreDataWrapper('cfg')\n        // this.mask_blur =\n\n        this.denoising_strength = createUIElement(\n            () => {\n                return sd_tab_store.data.denoising_strength\n            },\n            (value: number) => {\n                sd_tab_store.data.denoising_strength = value\n            }\n        )\n\n        this.mask_content = createUIElement(\n            html_manip.getMaskContent,\n            html_manip.setMaskContent\n        )\n        this.seed = createUIElement(\n            () => {\n                return sd_tab_store.data.seed\n            },\n            (value: string) => {\n                sd_tab_store.data.seed = value\n            }\n        )\n\n        this.mask_blur = createUIElement(\n            () => {\n                return sd_tab_store.data.mask_blur\n            },\n            (value: number) => {\n                sd_tab_store.data.mask_blur = value\n            }\n        )\n\n        this.mask_expansion = createUIElement(\n            html_manip.getMaskExpansion,\n            html_manip.setMaskExpansion\n        )\n        this.samplers = createUIElement(\n            () => {\n                return sd_tab_store.data.sampler_name\n            },\n            (value: string) => {\n                sd_tab_store.data.sampler_name = value\n            }\n        )\n\n        this.uiElements = {\n            // model: null,\n            // prompt_shortcut: null,\n            prompt: this.prompt,\n            negative_prompt: this.negative_prompt,\n            // selection_mode: null,\n            mode: this.mode,\n            batch_size: this.batch_size,\n            batch_count: this.batch_count,\n            steps: this.steps,\n            width: this.width,\n            height: this.height,\n\n            cfg_scale: this.cfg,\n            denoising_strength: this.denoising_strength,\n            // hi_res_denoising_strength:0.7,\n            mask_blur: this.mask_blur,\n            mask_expansion: this.mask_expansion,\n            // inpaint_at_full_res: false,\n            // hi_res_fix:false,\n            // inpaint_padding:0,\n            seed: this.seed,\n            sampler_index: this.samplers,\n            mask_content: this.mask_content,\n            cfg: this.cfg,\n            samplers: this.samplers,\n        }\n    }\n\n    autoFillInSettings(settings: any) {\n        for (const [name, value] of Object.entries(settings)) {\n            if (this.uiElements.hasOwnProperty(name) && value) {\n                //get the values for debugging\n                const old_value = this.uiElements[name].getValue()\n                console.log(\n                    '(name,old_value) => newValue:',\n                    name,\n                    old_value,\n                    value\n                )\n                //set the value\n                this.uiElements[name].setValue(value)\n            }\n        }\n    }\n    getSettings() {\n        let settings: any = {}\n        for (const [name, ui_element] of Object.entries(this.uiElements)) {\n            if (ui_element) {\n                const value = ui_element.getValue()\n                settings[name] = value\n            }\n        }\n        return settings\n    }\n\n    saveAsJson(json_file_name: string, settings: any) {\n        for (const [name, value] of Object.entries(settings)) {\n            if (this.uiElements.hasOwnProperty(name) && value) {\n                //get the values for debugging\n                const old_value = this.uiElements[name].getValue()\n                console.log(\n                    '(name,old_value) => newValue:',\n                    name,\n                    old_value,\n                    value\n                )\n\n                //set the value\n            }\n        }\n    }\n}\n// const ui_settings = new UISettings()\n\nfunction loadLatentNoiseSettings(ui_settings: any) {\n    loadPreset(ui_settings, LatentNoiseSettings)\n}\n\nfunction loadFillSettings(ui_settings: any) {\n    loadPreset(ui_settings, FillSettings)\n}\nfunction loadOriginalSettings(ui_settings: any) {\n    loadPreset(ui_settings, OriginalSettings)\n}\nasync function loadHealBrushSettings(ui_settings: any) {\n    document.getElementById('rbModeInpaint')!.click()\n\n    loadPreset(ui_settings, HealBrushSettings)\n}\n\nfunction loadCustomPresetsSettings() {}\nasync function mapCustomPresetsToLoaders(ui_settings_obj: any) {\n    const name_to_settings_obj = await getAllCustomPresetsSettings()\n    const preset_name_to_loader_obj: any = {}\n    for (const [preset_name, preset_settings] of Object.entries(\n        name_to_settings_obj\n    )) {\n        preset_name_to_loader_obj[preset_name] = () => {\n            loadCustomPreset(ui_settings_obj, preset_settings)\n        }\n    }\n    return preset_name_to_loader_obj\n}\n\nconst g_nativePresets = {\n    fill: loadFillSettings,\n    original: loadOriginalSettings,\n    'latent noise': loadLatentNoiseSettings,\n    'Heal Brush': loadHealBrushSettings,\n}\nexport function getNativeSDPresets() {\n    return g_nativePresets\n}\nlet g_ui_settings_object = new UISettings()\nfunction getUISettingsObject() {\n    return g_ui_settings_object\n}\n\n//REFACTOR: move to ui.js\nfunction addPresetMenuItem(preset_title: string) {\n    // console.log(model_title,model_name)\n    const menu_item_element = document.createElement('sp-menu-item')\n    menu_item_element.className = 'mPresetMenuItem'\n    menu_item_element.innerHTML = preset_title\n\n    // menu_item_element.addEventListener('select',()=>{\n    //   preset_func(g_ui_settings)\n    // })\n    return menu_item_element\n}\n//REFACTOR: move to ui.js\n// async function populatePresetMenu() {\n//     document.getElementById('mPresetMenu')!.innerHTML = ''\n//     const divider_elem = document.createElement('sp-menu-divider')\n//     const preset_name = 'Select Smart Preset'\n//     // const preset_func = () => {}\n//     const dummy_preset_item = addPresetMenuItem(preset_name)\n//     dummy_preset_item.setAttribute('selected', 'selected')\n//     // dummy_preset_item.setAttribute('disabled')\n//     document.getElementById('mPresetMenu')!.appendChild(dummy_preset_item)\n//     document.getElementById('mPresetMenu')!.appendChild(divider_elem)\n//     const presets = await getLoadedPresets(g_ui_settings_object)\n//     for (const [key, value] of Object.entries(presets)) {\n//         const preset_menu_item = addPresetMenuItem(key)\n//         document.getElementById('mPresetMenu')!.appendChild(preset_menu_item)\n//     }\n// }\n\n// populatePresetMenu()\n//REFACTOR: move to preset_tab.js\n// document\n//     .getElementById('mPresetMenu')!\n//     .addEventListener('change', async (evt: any) => {\n//         const preset_index = evt.target.selectedIndex\n//         const preset_name: string = evt.target.options[preset_index].textContent\n//         const presets: any = await getLoadedPresets(g_ui_settings_object)\n//         if (presets.hasOwnProperty(preset_name)) {\n//             const loader = presets[preset_name]\n//             if (loader.constructor.name === 'AsyncFunction') {\n//                 await loader(g_ui_settings_object)\n//             } else {\n//                 loader(g_ui_settings_object)\n//             }\n//         }\n//     })\n\n// {\n//     sd_tab:\n//     controlnet_tab:\n//     settings_tab:\n// }\nexport {\n    UI,\n    UIElement,\n    UISettings,\n    loadLatentNoiseSettings,\n    loadFillSettings,\n    loadHealBrushSettings,\n    getUISettingsObject,\n    // populatePresetMenu,\n}\n"
  },
  {
    "path": "typescripts/viewer/preview.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport { Collapsible } from '../util/collapsible'\nimport { observer } from 'mobx-react'\nimport { AStore } from '../main/astore'\n// import { progress } from '../entry'\nimport * as progress from '../session/progress'\n\nimport './style/preview.css'\nimport { reaction } from 'mobx'\nimport Locale from '../locale/locale'\nimport { ErrorBoundary } from '../util/errorBoundary'\nexport const store = new AStore({\n    // image: '',\n    // progress_value: 0,\n})\n// update all progress bar when progress store progress_value update\nreaction(\n    () => {\n        return progress.store.data.progress_value\n    },\n    (value: number) => {\n        document.querySelectorAll('.pProgressBars').forEach((progress: any) => {\n            progress.value = value?.toFixed(2)\n        })\n    }\n)\nconst Previewer = observer(() => {\n    const renderImage = () => {\n        let preview_img_html\n        if (progress.store.data.progress_image) {\n            preview_img_html = (\n                <img\n                    style={{ maxWidth: '100%' }}\n                    src={\n                        'data:image/png;base64,' +\n                        progress.store.data.progress_image\n                    }\n                />\n            )\n        }\n        return (\n            <div\n                className=\"progressImageContainer\"\n                style={{\n                    minHeight: progress.store.data.progress_image_height,\n                }}\n            >\n                <sp-progressbar\n                    class=\"pProgressBars preview_progress_bar\"\n                    max=\"100\"\n                    value={`${progress.store.data.progress_value}`}\n                ></sp-progressbar>\n                {progress.store.data.progress_image ? preview_img_html : void 0}\n            </div>\n        )\n    }\n    return <div style={{ padding: '4px' }}>{renderImage()}</div>\n})\n\nconst containers = document.querySelectorAll('.previewContainer')\n\nconst PreviewerContainer = observer(() => {\n    return (\n        <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n            <Collapsible\n                defaultIsOpen={true}\n                label={\n                    Locale('Preview') +\n                    ' ' +\n                    (progress.store.data.progress_value\n                        ? `: ${\n                              progress.store.data.progress_label\n                          } ${progress.store.data.progress_value?.toFixed(2)}%`\n                        : '')\n                }\n            >\n                <Previewer></Previewer>\n            </Collapsible>\n        </div>\n    )\n})\ncontainers.forEach((container) => {\n    const root = ReactDOM.createRoot(container)\n\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            <PreviewerContainer />\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n})\n"
  },
  {
    "path": "typescripts/viewer/style/preview.css",
    "content": ".preview_progress_bar {\n    border-left: 2px solid #3e3e3e;\n    border-right: 2px solid #3e3e3e;\n    margin: 0;\n    width: 100%;\n}\n"
  },
  {
    "path": "typescripts/viewer/viewer.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n// import ReactDOM from 'react-dom'\nimport { observer } from 'mobx-react'\nimport { AStore } from '../main/astore'\nimport { Grid } from '../util/grid'\nimport {\n    MoveToCanvasSvg,\n    SpCheckBox,\n    SpSlider,\n    SpSliderWithLabel,\n} from '../util/elements'\nimport {\n    convertGrayscaleToWhiteAndTransparent,\n    moveImageToLayer,\n    moveImageToLayer_old,\n} from '../util/ts/io'\nimport { io, layer_util, psapi, selection } from '../util/oldSystem'\nimport { Collapsible } from '../util/collapsible'\n// import { progress } from '../entry'\n\nimport * as progress from '../session/progress'\nimport * as settings_tab_ts from '../settings/settings'\n\nimport { store as session_store } from '../session/session_store'\nimport { reaction } from 'mobx'\nimport {\n    GenerationModeEnum,\n    MaskModeEnum,\n    SelectionInfoType,\n} from '../util/ts/enum'\nimport { base64ToLassoSelection } from '../../selection'\nimport { action, app, core } from 'photoshop'\nimport Locale from '../locale/locale'\nimport { applyMaskFromBlackAndWhiteImage } from '../util/ts/selection'\nimport { ErrorBoundary } from '../util/errorBoundary'\nimport { Session } from '../session/session'\nimport {\n    ClassNameEnum,\n    ClickTypeEnum,\n    init_store,\n    mask_store,\n    store,\n} from './viewer_util'\n\nconst executeAsModal = core.executeAsModal\nconst batchPlay = action.batchPlay\ndeclare let g_generation_session: any\n\nfunction findClickType(event: any) {\n    let click_type: ClickTypeEnum = ClickTypeEnum.Click\n\n    if (event.shiftKey) {\n        click_type = ClickTypeEnum.ShiftClick\n    } else if (event.altKey) {\n        click_type = ClickTypeEnum.AltClick\n    }\n    return click_type\n}\n\nconst timer = (ms: any) => new Promise((res) => setTimeout(res, ms))\n//when a generation is done, add the last generated image from the viewer to tha canvas\nreaction(\n    () => {\n        return store.data.images\n    },\n    async (images: string[]) => {\n        try {\n            if (images.length > 0) {\n                let attempts: number = 5\n                store.data.is_stored = Array(images.length).fill(false)\n                while (attempts > 0) {\n                    if (!progress.store.data.can_update) {\n                        await timer(2000)\n                        await handleOutputImageThumbnailClick(images.length - 1)\n                        break\n                    }\n\n                    attempts -= 1\n\n                    console.log('waiting 1000:')\n                    console.log(\n                        'progress.store.data.can_update:',\n                        progress.store.data.can_update\n                    )\n                    await timer(2000)\n                }\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n)\n\nconst add_new = async (\n    base64: string,\n    mask?: string,\n    selectionInfo?: SelectionInfoType,\n    mode?: GenerationModeEnum\n) => {\n    //change the color of thumbnail border\n    //add image to the canvas\n    await psapi.unselectActiveLayersExe()\n    const layer = await moveImageToLayer(\n        base64,\n        selectionInfo,\n        'output_image.png',\n        settings_tab_ts.store.data.use_smart_object\n    )\n\n    // create channel if the generated mode support masking\n    if (\n        [\n            GenerationModeEnum.Inpaint,\n            GenerationModeEnum.LassoInpaint,\n            GenerationModeEnum.Outpaint,\n        ].includes(mode!) &&\n        store.data.auto_mask &&\n        mask\n    ) {\n        const channel_mask_monochrome =\n            await convertGrayscaleToWhiteAndTransparent(mask)\n        if (\n            settings_tab_ts.store.data.b_borders_or_corners ===\n            MaskModeEnum.Transparent\n        ) {\n            //will use colorRange() which may or may not break\n            const mask_layer = await moveImageToLayer(\n                channel_mask_monochrome.base64,\n                selectionInfo\n            )\n\n            if (!mask_layer) {\n                throw new Error('mask_layer is empty')\n            }\n\n            await selection.black_white_layer_to_mask_multi_batchplay(\n                mask_layer.id,\n                layer.id,\n                'mask',\n                mask_store.data.expand_by\n            )\n            await layer_util.deleteLayers([mask_layer])\n        } else {\n            // if MaskModeEnum.Borders or MaskModeEnum.Corners\n            // another option that doesn't use colorRange()\n            await applyMaskFromBlackAndWhiteImage(\n                channel_mask_monochrome.base64,\n                layer.id,\n                selectionInfo,\n                settings_tab_ts.store.data.b_borders_or_corners,\n                mask_store.data.expand_by\n            )\n        }\n    }\n    return layer\n}\nconst add = async (\n    base64: string,\n    mask?: string,\n    selectionInfo?: SelectionInfoType, // TODO: don't make this optional\n    mode?: GenerationModeEnum //TODO: don't make mode optional\n) => {\n    try {\n        //change the color of thumbnail border\n        //add image to the canvas\n        const layer = await moveImageToLayer_old(base64, selectionInfo)\n\n        // create channel if the generated mode support masking\n        if (\n            [\n                GenerationModeEnum.Inpaint,\n                GenerationModeEnum.LassoInpaint,\n                GenerationModeEnum.Outpaint,\n            ].includes(mode!) &&\n            store.data.auto_mask\n        ) {\n            // const base64_monochrome_mask = await io.convertGrayscaleToMonochrome(\n            //     session_store.data.selected_mask\n            // )\n            const timer = (ms: any) => new Promise((res) => setTimeout(res, ms))\n\n            const mask_monochrome = await io.convertGrayscaleToMonochrome(\n                // session_store.data.expanded_mask\n                mask\n            )\n            const channel_mask = mask_monochrome\n            // const selectionInfo = selectionInfo\n            // await selection.base64ToChannel(channel_mask, selectionInfo, 'mask')\n\n            await applyMaskFromBlackAndWhiteImage(\n                channel_mask,\n                layer.id,\n                selectionInfo,\n                settings_tab_ts.store.data.b_borders_or_corners,\n                mask_store.data.expand_by\n            )\n        }\n\n        return layer\n    } catch (e) {\n        console.error(e)\n    }\n}\nexport const addWithHistory = async (\n    base64: string,\n    mask?: string,\n    selectionInfo?: SelectionInfoType,\n    mode?: GenerationModeEnum\n) => {\n    let layer\n    await executeAsModal(\n        async (context: any) => {\n            let history_id\n            try {\n                history_id = await context.hostControl.suspendHistory({\n                    documentID: app.activeDocument.id,\n                    name: 'Add Image to Canvas',\n                })\n            } catch (e) {\n                console.warn(e)\n            }\n\n            layer = await add_new(base64, mask, selectionInfo, mode)\n\n            try {\n                await context.hostControl.resumeHistory(history_id)\n            } catch (e) {\n                console.warn(e)\n            }\n        },\n        {\n            commandName: 'Add Image to Canvas',\n        }\n    )\n    return layer\n}\n\nconst remove = async (layer: any) => {\n    await layer_util.deleteLayers([layer]) // delete previous layer\n}\n\nconst addAll = async () => {\n    let i = 0\n    for (let i = 0; i < store.data.images.length; i++) {\n        if (\n            store.data.is_stored[i] ||\n            layer_util.Layer.doesLayerExist(store.data.layers?.[i])\n        ) {\n            continue\n        }\n        await addWithHistory(\n            store.data.images[i],\n            mask_store.data?.output_images_masks?.[i] ?? void 0,\n            session_store.data.selectionInfo,\n            session_store.data.mode\n        )\n    }\n\n    Session.endSession()\n}\nconst discardAll = async () => {\n    for (let i = 0; i < store.data.images.length; i++) {\n        await remove(store.data.layers[i])\n    }\n\n    Session.endSession()\n}\nconst onlySelected = () => {\n    Session.endSession()\n}\nexport const handleOutputImageThumbnailClick = async (\n    index: number,\n    event?: any\n) => {\n    try {\n        if (!store.data.can_click) return null\n\n        store.data.can_click = false\n        const prev_index = store.data.prev_index\n        const image = store.data.images[index] || ''\n        const is_stored = store.data.is_stored[index] || false\n        const is_prev_stored = store.data.is_stored[prev_index] || false\n        const prev_layer = store.data.layers[prev_index] || null\n        const prev_image = store.data.images[prev_index] || ''\n\n        console.log('prev_index:', prev_index)\n        console.log('is_stored:', is_stored)\n        console.log('is_prev_stored:', is_prev_stored)\n        console.log('prev_layer:', prev_layer)\n\n        // store.updateProperty('clicked_index', index)\n\n        let click_type: ClickTypeEnum = event\n            ? findClickType(event)\n            : ClickTypeEnum.Click\n        if (\n            index === store.data.prev_index &&\n            click_type === ClickTypeEnum.Click\n        ) {\n            click_type = ClickTypeEnum.SecondClick\n            //toggle functionality\n        }\n\n        console.log('click_type:', click_type)\n        if (click_type === ClickTypeEnum.Click) {\n            //1) modify layer stacks\n\n            const layer = await addWithHistory(\n                image,\n                mask_store.data?.output_images_masks?.[index] ?? void 0,\n                session_store.data.selectionInfo,\n                session_store.data.mode\n            )\n            await remove(store.data.layers[index])\n            console.log('layer:', layer)\n            store.data.layers[index] = layer\n\n            if (is_prev_stored) {\n            } else {\n                await remove(prev_layer)\n            }\n            //2)change style\n            store.data.class_name[prev_index] = is_prev_stored\n                ? ClassNameEnum.Green\n                : ClassNameEnum.None\n\n            store.data.class_name[index] = is_stored\n                ? ClassNameEnum.Green\n                : ClassNameEnum.Orange\n\n            //3)modify index\n            store.data.prev_index = index\n        } else if (click_type === ClickTypeEnum.ShiftClick) {\n            //1) modify layer stacks\n            if (prev_index === index) {\n                store.data.class_name[index] = ClassNameEnum.Green\n            } else {\n                if (is_prev_stored) {\n                } else {\n                    // await remove(prev_layer)\n                }\n\n                const layer = await addWithHistory(\n                    image,\n                    mask_store.data?.output_images_masks?.[index] ?? void 0,\n                    session_store.data.selectionInfo,\n                    session_store.data.mode\n                )\n                await remove(store.data.layers[index])\n                store.data.layers[index] = layer\n                //2)change style\n                store.data.class_name[prev_index] = ClassNameEnum.Green\n                store.data.class_name[index] = ClassNameEnum.Green\n\n                //3)store index\n                store.data.is_stored[prev_index] = true\n                store.data.is_stored[index] = true\n                store.data.prev_index = index\n            }\n        } else if (click_type === ClickTypeEnum.AltClick) {\n            //1) modify layer stacks\n            if (is_prev_stored) {\n            } else {\n                await remove(prev_layer)\n            }\n            await remove(store.data.layers[index])\n            //2)change style\n            store.data.class_name[prev_index] = is_prev_stored\n                ? ClassNameEnum.Green\n                : ClassNameEnum.None\n            store.data.class_name[index] = ClassNameEnum.None\n\n            //3)store index\n            store.data.prev_index = -1\n            store.data.is_stored[index] = false\n        } else if (click_type === ClickTypeEnum.SecondClick) {\n            //1) modify layer stacks\n            if (is_prev_stored) {\n            } else {\n                await remove(prev_layer)\n            }\n\n            //2)change style\n            store.data.class_name[prev_index] = is_prev_stored\n                ? ClassNameEnum.Green\n                : ClassNameEnum.None\n\n            //3)store index\n            store.data.prev_index = -1\n        }\n        store.data.class_name = [...store.data.class_name]\n    } catch (e) {\n        console.warn(e)\n    }\n    store.data.can_click = true\n}\nconst Viewer = observer(() => {\n    // console.log('rendered', store.toJsFunc())\n    const display_button: Boolean =\n        session_store.data.is_active && session_store.data.can_generate\n    const button_style = {\n        display: display_button ? 'block' : 'none',\n        marginRight: '3px',\n    }\n    return (\n        <div>\n            <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                <Collapsible defaultIsOpen={true} label={Locale('Viewer')}>\n                    <SpSliderWithLabel\n                        out_min={50}\n                        out_max={300}\n                        in_min={1}\n                        in_max={10}\n                        // min={85}\n                        // max={300}\n\n                        onSliderChange={(new_value: number) =>\n                            // event: React.ChangeEvent<HTMLInputElement>\n                            {\n                                try {\n                                    console.log('change event triggered!')\n                                    // const new_value = event.target.value\n                                    // const base_width = 100\n                                    // const scale_ratio = new_value / base_width\n\n                                    // store.updateProperty('height', scale_ratio)\n                                    store.updateProperty('width', new_value)\n                                    init_store.updateProperty(\n                                        'width',\n                                        new_value\n                                    )\n                                } catch (e) {\n                                    console.warn(e)\n                                }\n                            }\n                        }\n                        show-value={false}\n                        steps={1}\n                        output_value={store.data.width}\n                        label=\"Thumbnail Size\"\n                    ></SpSliderWithLabel>\n\n                    <div\n                        style={{\n                            display: 'flex',\n                            justifyContent: 'space-evenly',\n                            paddingTop: '3px',\n                        }}\n                    >\n                        <button\n                            title={Locale(\n                                'Keep all generated images on the canvas'\n                            )}\n                            className=\"btnSquare acceptClass acceptAllImgBtn\"\n                            style={button_style}\n                            onClick={addAll}\n                        ></button>\n                        <button\n                            title={Locale(\n                                'Delete all generated images from the canvas'\n                            )}\n                            className=\"btnSquare discardClass discardAllImgBtn\"\n                            style={button_style}\n                            onClick={discardAll}\n                        ></button>\n                        <button\n                            title={Locale('Keep only the highlighted images')}\n                            className=\"btnSquare acceptSelectedClass acceptSelectedImgBtn\"\n                            style={button_style}\n                            onClick={onlySelected}\n                        ></button>\n                    </div>\n                    <div>\n                        <SpCheckBox\n                            style={{\n                                display: [\n                                    GenerationModeEnum.Inpaint,\n                                    GenerationModeEnum.LassoInpaint,\n                                    GenerationModeEnum.Outpaint,\n                                ].includes(session_store.data.mode)\n                                    ? void 0\n                                    : 'none',\n                                marginRight: '10px',\n                            }}\n                            onChange={(event: any) => {\n                                store.data.auto_mask = event.target.checked\n                            }}\n                            checked={store.data.auto_mask}\n                        >\n                            {\n                                //@ts-ignore\n                                Locale('Apply Auto Masking')\n                            }\n                        </SpCheckBox>\n                        <SpSlider\n                            show-value=\"false\"\n                            min={0}\n                            max={300}\n                            value={mask_store.data.expand_by}\n                            onInput={(evt: any) => {\n                                mask_store.data.expand_by = evt.target.value\n                            }}\n                            title=\"expand the Photoshop masking by x pixels\"\n                        >\n                            <sp-label slot=\"label\">\n                                {Locale('Expand by')}{' '}\n                            </sp-label>\n                            <sp-label slot=\"label\">\n                                {mask_store.data.expand_by}\n                            </sp-label>\n                        </SpSlider>\n                    </div>\n                    <div\n                        style={{ border: '2px solid #6d6c6c', padding: '3px' }}\n                    >\n                        <Grid\n                            // images={init_store.data.images}\n                            thumbnails={init_store.data.thumbnails}\n                            thumbnails_styles={init_store.data.class_name}\n                            callback={(index: number, event: any) => {\n                                console.log(index)\n                            }}\n                            width={init_store.data.width}\n                            height={init_store.data.height}\n                            // clicked_index={init_store.data.clicked_index}\n                            // permanent_indices={init_store.data.permanent_indices}\n                        ></Grid>\n                    </div>\n                    <div\n                        style={{ border: '2px solid #6d6c6c', padding: '3px' }}\n                    >\n                        <Grid\n                            // images={mask_store.data.images}\n                            thumbnails={mask_store.data.thumbnails}\n                            thumbnails_styles={mask_store.data.class_name}\n                            callback={(index: number, event: any) => {\n                                console.log(index)\n                            }}\n                            width={mask_store.data.width}\n                            height={mask_store.data.height}\n                            // clicked_index={init_store.data.clicked_index}\n                            // permanent_indices={init_store.data.permanent_indices}\n                            action_buttons={[\n                                {\n                                    ComponentType: MoveToCanvasSvg,\n                                    callback: async (index: number) => {\n                                        await moveImageToLayer(\n                                            mask_store.data.images[index],\n                                            session_store.data.selectionInfo,\n                                            'mask'\n                                        )\n                                    },\n                                },\n                            ]}\n                        ></Grid>\n                    </div>\n                    <div\n                        style={{ border: '2px solid #6d6c6c', padding: '3px' }}\n                    >\n                        <Grid\n                            // images={store.data.images}\n                            thumbnails={store.data.thumbnails}\n                            thumbnails_styles={store.data.class_name}\n                            callback={handleOutputImageThumbnailClick}\n                            width={store.data.width}\n                            height={store.data.height}\n                            clicked_index={store.data.clicked_index}\n                            permanent_indices={store.data.permanent_indices}\n                            // action_buttons={[\n                            //     {\n                            //         ComponentType: MoveToCanvasSvg,\n                            //         callback: (index: number) => {\n                            //             console.log(\n                            //                 'viewer callback:',\n                            //                 store.data.images[index],\n                            //                 g_generation_session.selectionInfo\n                            //             )\n                            //             moveImageToLayer(\n                            //                 store.data.images[index],\n                            //                 g_generation_session.selectionInfo\n                            //             )\n                            //         },\n                            //     },\n                            // ]}\n                        ></Grid>\n                    </div>\n                </Collapsible>\n            </div>\n        </div>\n    )\n})\n\nconst ToolbarViewerButtons = observer(() => {\n    const display_button: Boolean =\n        session_store.data.is_active && session_store.data.can_generate\n    const button_style = {\n        display: display_button ? 'block' : 'none',\n\n        marginRight: '3px',\n        marginBottom: '3px',\n    }\n    return (\n        <div\n        // style={{\n        //     display: 'flex',\n        //     justifyContent: 'space-evenly',\n        //     paddingTop: '3px',\n        // }}\n        >\n            <button\n                title={Locale('Keep all generated images on the canvas')}\n                className=\"btnSquare acceptClass acceptAllImgBtn\"\n                style={button_style}\n                onClick={addAll}\n            ></button>\n            <button\n                title={Locale('Delete all generated images from the canvas')}\n                className=\"btnSquare discardClass discardAllImgBtn\"\n                style={button_style}\n                onClick={discardAll}\n            ></button>\n            <button\n                title={Locale('Keep only the highlighted images')}\n                className=\"btnSquare acceptSelectedClass acceptSelectedImgBtn\"\n                style={button_style}\n                onClick={onlySelected}\n            ></button>\n        </div>\n    )\n})\n\n// const node = document.getElementById('reactViewerContainer')!\nconst containers = document.querySelectorAll('.reactViewerContainer')\n\ncontainers.forEach((container) => {\n    const root = ReactDOM.createRoot(container)\n    root.render(\n        //<React.StrictMode>\n        <ErrorBoundary>\n            {/* <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>\n                    <Collapsible defaultIsOpen={true} label={Locale('Viewer')}>\n                        <Viewer></Viewer>\n                    </Collapsible>\n                </div> */}\n            <Viewer></Viewer>\n        </ErrorBoundary>\n        //</React.StrictMode>\n    )\n})\n\nconst button_container = document.getElementById('viewerButtonContainer')!\nconst root = ReactDOM.createRoot(button_container)\nroot.render(\n    //<React.StrictMode>\n    <ErrorBoundary>\n        <ToolbarViewerButtons />\n    </ErrorBoundary>\n    //</React.StrictMode>\n)\n"
  },
  {
    "path": "typescripts/viewer/viewer_util.ts",
    "content": "import { AStore } from '../main/astore'\nimport { io } from '../util/oldSystem'\n\nexport enum ClickTypeEnum {\n    Click = 'click',\n    ShiftClick = 'shift_click',\n    AltClick = 'alt_click',\n    SecondClick = 'second_click', //when we click a thumbnail that is active/ has orange border\n}\n\nexport enum OutputImageStateEnum {\n    Add = 'add',\n    remove = 'remove',\n}\nexport enum ClassNameEnum {\n    Green = 'viewerImgSelected',\n    Orange = 'viewerImgActive',\n    None = '',\n}\ninterface AStoreData {\n    images: string[]\n    thumbnails: string[]\n    metadata: any[] // metadata for each image\n    width: number\n    height: number\n\n    prev_layer: any\n    clicked_index: number | undefined\n\n    permanent_indices: number[]\n\n    prev_index: number\n    is_stored: boolean[]\n    layers: any[]\n    class_name: ClassNameEnum[]\n    can_click: boolean\n    auto_mask: boolean\n}\nexport const store = new AStore<AStoreData>({\n    images: [],\n    thumbnails: [],\n    metadata: [], // metadata for each image\n    width: 50,\n    height: 50,\n\n    prev_layer: null,\n    clicked_index: undefined,\n\n    permanent_indices: [],\n\n    prev_index: -1,\n\n    is_stored: [],\n    layers: [],\n    class_name: [],\n    can_click: true,\n    auto_mask: true,\n})\nexport const init_store = new AStore({\n    images: [],\n    thumbnails: [],\n\n    width: 50,\n    height: 50,\n\n    prev_layer: null,\n    clicked_index: null,\n\n    permanent_indices: [],\n\n    prev_index: -1,\n    output_image_obj_list: [],\n    is_stored: [],\n    layers: [],\n    class_name: [],\n    can_click: true,\n})\nexport const mask_store = new AStore({\n    images: [],\n    thumbnails: [],\n    output_images_masks: [] as string[],\n\n    width: 50,\n    height: 50,\n    expand_by: 0,\n    prev_layer: null,\n    clicked_index: null,\n\n    permanent_indices: [],\n\n    prev_index: -1,\n    output_image_obj_list: [],\n    is_stored: [],\n    layers: [],\n    class_name: [],\n    can_click: true,\n})\n\ninterface AStoreDataWithImagesAndThumbnails {\n    images: string[]\n    thumbnails: string[]\n}\n\nexport async function updateViewerStoreImageAndThumbnail<\n    T extends AStoreDataWithImagesAndThumbnails\n>(store: AStore<T>, images: string[]) {\n    try {\n        if (typeof images === 'undefined' || !images) {\n            return null\n        }\n        store.data.images = images\n        const thumbnail_list = []\n        for (const base64 of images) {\n            const thumbnail = await io.createThumbnail(base64, 300)\n            thumbnail_list.push(thumbnail)\n        }\n\n        store.data.thumbnails = thumbnail_list\n    } catch (e) {\n        console.warn(e)\n        console.warn('images: ', images)\n    }\n}\n\nexport const resetViewer = () => {\n    store.updateProperty('images', [])\n    store.data.thumbnails = []\n    store.data.prev_index = -1\n    store.data.is_stored = []\n    store.data.layers = []\n    store.data.class_name = []\n    store.data.can_click = true\n\n    mask_store.data.images = []\n    mask_store.data.thumbnails = []\n    init_store.data.images = []\n    init_store.data.thumbnails = []\n}\n\nexport default {\n    store,\n    init_store,\n    mask_store,\n}\n"
  },
  {
    "path": "utility/api.js",
    "content": "//deprecated file don't use\n\nconsole.warn('api.js is deprecated, use typescript/util/ts/api.ts')\n\nasync function requestGet(url) {\n    let json = null\n\n    const full_url = url\n    try {\n        let request = await fetch(full_url)\n        if (request.status === 404) {\n            return null\n        }\n\n        json = await request.json()\n\n        // console.log('json: ', json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\nasync function requestPost(url, payload) {\n    let json = null\n\n    const full_url = url\n    try {\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n        })\n\n        if (request.status === 404) {\n            return null\n        }\n\n        json = await request.json()\n\n        // console.log('json: ', json)\n    } catch (e) {\n        console.warn(`issues requesting from ${full_url}`, e)\n    }\n    return json\n}\nasync function requestFormDataPost(url, payload) {\n    try {\n        var myHeaders = new Headers()\n        myHeaders.append('Cookie', 'PHPSESSID=n70fa2vmvm6tfmktf4jmstmd1i')\n\n        var formdata = new FormData()\n\n        for ([key, value] of Object.entries(payload)) {\n            formdata.append(key, value)\n        }\n        // formdata.append(\n        //     'source',\n        //     'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII='\n        // )\n        // formdata.append('key', '6d207e02198a847aa98d0a2a901485a5')\n\n        var requestOptions = {\n            method: 'POST',\n            headers: myHeaders,\n            body: formdata,\n            redirect: 'follow',\n        }\n\n        const response = await fetch(url, requestOptions)\n        const result_json = response.json()\n        return result_json\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nmodule.exports = {\n    requestGet,\n    requestPost,\n    requestFormDataPost,\n}\n"
  },
  {
    "path": "utility/dummy.js",
    "content": "function getDummyBase64() {\n    const b64Image =\n        'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'\n    return b64Image\n}\nfunction getDummyBase64_2() {\n    const b64Image =\n        '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'\n    return b64Image\n}\nfunction getDummyWebpBase64() {\n    // const b64ImageWebp = `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`\n    const b64webp = `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`\n    return b64webp\n}\n\nmodule.exports = {\n    getDummyBase64,\n    getDummyBase64_2,\n    getDummyWebpBase64,\n}\n"
  },
  {
    "path": "utility/general.js",
    "content": "const { requestGet } = require('./api')\n\nfunction newOutputImageName(format = 'png') {\n    const random_id = Math.floor(Math.random() * 100000000000 + 1) // Date.now() doesn't have enough resolution to avoid duplicate\n    const image_name = `output- ${Date.now()}-${random_id}.${format}`\n    console.log('generated image name:', image_name)\n    return image_name\n}\n\nfunction makeImagePath(format = 'png') {\n    const image_name = newOutputImageName(format)\n    const image_path = `${uniqueDocumentId}/${image_name}`\n    return image_path\n}\nfunction convertImageNameToPng(image_name) {\n    const image_png_name = image_name.split('.')[0] + '.png'\n    return image_png_name\n}\nfunction fixNativePath(native_path) {\n    const fixed_native_path = native_path.replaceAll('\\\\', '/')\n\n    return fixed_native_path\n}\nfunction base64ToBase64Url(base64_image) {\n    return 'data:image/png;base64,' + base64_image\n}\nfunction base64UrlToBase64(base64_url) {\n    const base64_image = base64_url.replace('data:image/png;base64,', '')\n    return base64_image\n}\nconst timer = (ms) => new Promise((res) => setTimeout(res, ms)) //Todo: move this line to it's own utilit function\n\nfunction mapRange(x, in_min, in_max, out_min, out_max) {\n    return ((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min\n}\n\nfunction compareVersions(version_1, version_2) {\n    //remove the first character v\n    version_1 = version_1.slice(1)\n    const increments_1 = version_1.split('.').map((sn) => parseInt(sn))\n\n    version_2 = version_2.slice(1)\n    const increments_2 = version_2.split('.').map((sn) => parseInt(sn))\n\n    let b_older = false // true if version_1 is < than version_2, false if version_1 >= older\n    for (let i = 0; i < increments_1.length; ++i) {\n        if (increments_1[i] < increments_2[i]) {\n            b_older = true\n            break\n        }\n    }\n    return b_older\n}\nasync function requestOnlineData() {\n    const { requestGet } = require('./api')\n    const online_data = await requestGet(g_online_data_url)\n    return online_data\n}\nfunction nearestMultiple(input, multiple) {\n    //use the following formula for finding the upper value instead of the lower.\n    //( ( x - 1 ) | ( m - 1 ) ) + 1\n    const nearest_multiple = input - (input % multiple)\n    return nearest_multiple\n}\n\nfunction sudoTimer(progress_text = 'Loading ControlNet...') {\n    //sudo timer that will count to 100 and update the progress bar.\n    //use it for controlNet since block api progress call\n    let current_time = 0\n    let max_time = 100\n    var timerId = setInterval(countdown, 1000)\n\n    function countdown() {\n        if (current_time > max_time) {\n            clearTimeout(timerId)\n            // doSomething()\n            // html_manip.updateProgressBarsHtml(0)\n        } else {\n            html_manip.updateProgressBarsHtml(current_time, progress_text)\n            console.log(current_time + ' seconds remaining')\n            current_time++\n        }\n    }\n    return timerId\n}\nfunction countNewLines(string) {\n    const count = (string.match(/[\\n\\r]/g) || []).length\n    // console.log(count)\n    return count\n}\nmodule.exports = {\n    newOutputImageName,\n    makeImagePath,\n    convertImageNameToPng,\n    fixNativePath,\n    base64ToBase64Url,\n    base64UrlToBase64,\n    timer,\n\n    mapRange,\n    compareVersions,\n    requestOnlineData,\n    nearestMultiple,\n    sudoTimer,\n    countNewLines,\n}\n"
  },
  {
    "path": "utility/html_manip.js",
    "content": "////// Start Prompt//////////\n\nfunction autoFillInPrompt(prompt_value) {\n    // document.getElementById('taPrompt').value = prompt_value\n    multiPrompts.setPrompt({ positive: prompt_value })\n}\n\n////// End Prompt//////////\n\n////// Start Negative Prompt//////////\n\nfunction autoFillInNegativePrompt(negative_prompt_value) {\n    // document.getElementById('taNegativePrompt').value = negative_prompt_value\n    multiPrompts.setPrompt({ negative: negative_prompt_value })\n}\n\n////// End Negative Prompt//////////\n\n////// Start Width//////////\n\nfunction getWidth() {\n    return sd_tab_store.data.width\n}\n\nfunction getHrWidth() {\n    slider_width = document.getElementById('hrWidth').value\n    const width = slider_width * 64\n    return width\n}\n\nfunction getHrHeight() {\n    slider_width = document.getElementById('hrHeight').value\n    const width = slider_width * 64\n    return width\n}\nasync function autoFillInWidth(width_value) {\n    sd_tab_store.data.width = width_value\n    sd_tab_util.helper_store.data.previous_width = width_value\n\n    sd_tab_store.data.ratio =\n        await selection.Selection.getImageToSelectionDifference()\n}\n////// End Width//////////\n\n////// Start Height//////////\n\nfunction getHeight() {\n    // slider_value = document.getElementById('slHeight').value\n    // const height = slider_value * 64\n    return sd_tab_store.data.height\n}\n\nasync function autoFillInHeight(height_value) {\n    sd_tab_util.helper_store.data.previous_height = height_value\n    sd_tab_store.data.height = height_value\n    //update the label\n    sd_tab_store.data.ratio =\n        await selection.Selection.getImageToSelectionDifference()\n}\n\nfunction autoFillInHRHeight(height_value) {\n    sd_tab_store.data.hr_resize_y = height_value\n}\n\nfunction autoFillInHRWidth(width_value) {\n    sd_tab_store.data.hr_resize_x = width_value\n}\n\n//get the stable diffusion ready value from the slider with  \"slider_id\"\n//REFACTOR: delete, getSliderSdValue_Old is deprecated, instead use getSliderSdValue\nfunction getSliderSdValue_Old(slider_id, multiplier) {\n    // console.warn(\n    //     'getSliderSdValue_Old is deprecated, instead use getSliderSdValue'\n    // )\n    const slider_value = document.getElementById(slider_id).value\n    const sd_value = slider_value * multiplier\n    return sd_value\n}\n//REFACTOR: delete, autoFillInSliderUi is deprecated, instead use setSliderSdValue\nfunction autoFillInSliderUi(sd_value, slider_id, label_id, multiplier) {\n    // console.warn(\n    //     'autoFillInSliderUi is deprecated, instead use setSliderSdValue'\n    // )\n    //update the slider\n    document.getElementById(slider_id).value = `${sd_value * multiplier}`\n    //update the label\n    document.getElementById(label_id).innerHTML = `${sd_value}`\n}\n\nfunction getSliderSdValue(\n    slider_id,\n    slider_start,\n    slider_end,\n    sd_start,\n    sd_end\n) {\n    const slider_value = document.getElementById(slider_id).value\n    // const sd_value = general.mapRange(slider_value, 0, 100, 0, 1) // convert slider value to SD ready value\n    const sd_value = general.mapRange(\n        slider_value,\n        slider_start,\n        slider_end,\n        sd_start,\n        sd_end\n    ) // convert slider value to SD ready value\n\n    return sd_value\n}\nfunction setSliderSdValue(\n    slider_id,\n    label_id,\n    sd_value,\n    slider_start,\n    slider_end,\n    sd_start,\n    sd_end\n) {\n    const slider_value = general.mapRange(\n        sd_value,\n        sd_start,\n        sd_end,\n        slider_start,\n        slider_end\n    ) // convert slider value to SD ready value\n    document.getElementById(slider_id).value = slider_value.toString()\n    document.getElementById(label_id).innerHTML = sd_value.toString()\n}\nfunction getSliderSdValueByElement(\n    slider_element,\n    slider_start,\n    slider_end,\n    sd_start,\n    sd_end\n) {\n    const slider_value = slider_element.value\n    // const sd_value = general.mapRange(slider_value, 0, 100, 0, 1) // convert slider value to SD ready value\n    const sd_value = general.mapRange(\n        slider_value,\n        slider_start,\n        slider_end,\n        sd_start,\n        sd_end\n    ) // convert slider value to SD ready value\n\n    return sd_value\n}\nfunction setSliderSdValueByElements(\n    slider_element,\n    label_element,\n    sd_value,\n    slider_start,\n    slider_end,\n    sd_start,\n    sd_end\n) {\n    const slider_value = general.mapRange(\n        sd_value,\n        sd_start,\n        sd_end,\n        slider_start,\n        slider_end\n    ) // convert slider value to SD ready value\n    slider_element.value = slider_value.toString()\n    label_element.innerHTML = sd_value.toString()\n}\n\nfunction autoFillInHiResFixs(firstphase_width, firstphase_height) {\n    //update the firstphase width slider and label\n    autoFillInSliderUi(firstphase_width, 'hrWidth', 'hWidth', 1.0 / 64)\n    //update the firstphase height slider and label\n    autoFillInSliderUi(firstphase_height, 'hrHeight', 'hHeight', 1.0 / 64)\n}\n////// End Hi Res Fix//////////\n\n////// Start Inpaint Mask Weight//////////\nfunction autoFillInInpaintMaskWeight(sd_value) {\n    //update the inpaint mask weight\n    autoFillInSliderUi(\n        sd_value,\n        'slInpaintingMaskWeight',\n        'lInpaintingMaskWeight',\n        100\n    )\n}\n////// End Inpaint Mask Weight//////////\n\n////// Start Samplers//////////\nfunction unCheckAllSamplers() {\n    document\n        .getElementsByClassName('rbSampler')\n\n        .forEach((e) => e.removeAttribute('checked'))\n}\n\nfunction getSelectedRadioButtonElement(rbClass) {\n    try {\n        const rb_element = [...document.getElementsByClassName(rbClass)].filter(\n            (e) => e.checked == true\n        )[0]\n        return rb_element\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction getSamplerElementByName(sampler_name) {\n    try {\n        //assume the sampler_name is valid\n        //return the first\n        //convert htmlCollection into an array, then user filter to get the radio button with the value equals to sampler_name\n        const sampler_element = [\n            ...document.getElementsByClassName('rbSampler'),\n        ].filter((e) => e.value == sampler_name)[0]\n        return sampler_element\n    } catch (e) {\n        console.warn(`Sampler '${sampler_name}' not found ${e}`)\n    }\n}\n\nfunction getBackendType() {\n    return [...document.getElementsByClassName('rbBackendType')].filter(\n        (e) => e.checked == true\n    )[0].value\n}\n\nfunction getHordeApiKey() {\n    let key = document.getElementById('tiHordeApiKey').value\n    const valid_key = key ? key : '0000000000'\n    return valid_key\n}\n\nfunction setHordeApiKey(key) {\n    document.getElementById('tiHordeApiKey').value = key\n}\nfunction checkSampler(sampler_name) {\n    sampler_element = getSamplerElementByName(sampler_name)\n    sampler_element.checked = true\n}\nfunction autoFillInSampler(sampler_name) {\n    // unCheckAllSamplers()\n    checkSampler(sampler_name)\n}\n////// End Samplers//////////\n\n////// Start Models//////////\n\nfunction getModelElementByHash(model_hash) {\n    try {\n        //assume the model_hash is valid\n        //return the first model menu item element with model_hash\n        const model_element = [\n            ...document.getElementsByClassName('mModelMenuItem'),\n        ].filter((e) => e.dataset.model_hash == model_hash)[0]\n        return model_element\n    } catch (e) {\n        console.warn(`Model '${model_hash}' not found ${e}`)\n    }\n}\nfunction getModelHashByTitle(model_title) {\n    //return find the model hash by it's title\n    try {\n        return [...document.getElementsByClassName('mModelMenuItem')].filter(\n            (e) => e.dataset.model_title == model_title\n        )[0].dataset.model_hash\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction getSelectedModelHash() {\n    //return the hash of the first selected model menu item\n    try {\n        return [...document.getElementsByClassName('mModelMenuItem')].filter(\n            (e) => e.selected == true\n        )[0].dataset.model_hash\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction selectModelUi(model_hash) {\n    model_element = getModelElementByHash(model_hash)\n    model_element.selected = true\n}\n\n////// End Models//////////\n\n////// Start Init Image && Init Image Mask//////////\n\nfunction getInitImageElement() {\n    const ini_image_element = document.getElementById('init_image')\n    return ini_image_element\n}\nfunction setInitImageSrc(image_src) {\n    const ini_image_element = getInitImageElement()\n    ini_image_element.src = image_src\n}\nfunction setControlImageSrc(image_src, element_index = 0) {\n    const control_net_image_element = document.querySelector(\n        `#controlnet_settings_${element_index} .control_net_image_`\n    )\n    // const control_net_image_element = document.getElementById(\n    //     'control_net_image' + '_' + element_index\n    // )\n    control_net_image_element.src = image_src\n}\n\nfunction setProgressImageSrc(image_src) {\n    // const progress_image_element = document.getElementById('progressImage')\n\n    const progress_image_element = document.getElementById(\n        'divProgressImageViewerContainer'\n    )\n    // progress_image_element.src = image_src\n\n    progress_image_element.style.backgroundSize = 'contain'\n    progress_image_element.style.height = '500px'\n\n    progress_image_element.style.backgroundImage = `url('${image_src}')`\n}\n\nfunction getInitImageMaskElement() {\n    const ini_image_mask_element = document.getElementById('init_image_mask')\n    return ini_image_mask_element\n}\nfunction setInitImageMaskSrc(image_src) {\n    const ini_image_mask_element = getInitImageMaskElement()\n    ini_image_mask_element.src = image_src\n}\n////// End Init Image && Init Image Mask//////////\n\n////// Start Generate Buttons //////////\n\n////// End Generate Buttons //////////\n\n////// Start Servers Status //////////\n\nfunction setAutomaticStatus(newStatusClass, oldStatusClass) {\n    document.getElementById('automaticStatus').classList.add(newStatusClass)\n    document.getElementById('automaticStatus').classList.remove(oldStatusClass)\n}\nfunction setProxyServerStatus(newStatusClass, oldStatusClass) {\n    document.getElementById('proxyServerStatus').classList.add(newStatusClass)\n    document\n        .getElementById('proxyServerStatus')\n        .classList.remove(oldStatusClass)\n}\n////// End Servers Status //////////\n\n////// Start Reset Settings Button //////////\n\nfunction getBatchNumber() {\n    // return document.getElementById('tiNumberOfImages').value\n    return document.getElementById('tiNumberOfBatchSize').value\n}\nfunction autoFillInBatchNumber(batch_number) {\n    // document.getElementById('tiNumberOfImages').value = String(batch_number)\n    document.getElementById('tiNumberOfBatchSize').value = String(batch_number)\n}\n\nfunction setCFG(cfg_value) {\n    sd_tab_store.data.cfg = cfg_value\n}\nfunction getCFG() {\n    return sd_tab_store.data.cfg\n}\n\nfunction autoFillSettings(settings) {\n    try {\n        //reset all UI settings except model selection and sampler selection\n\n        multiPrompts.setPrompt({ positive: settings['positive_prompt'] })\n        multiPrompts.setPrompt({ negative: settings['negative_prompt'] })\n        autoFillInBatchNumber(settings['batch_number'])\n        sd_tab_store.data.steps = settings['steps']\n        autoFillInWidth(settings['width'])\n        autoFillInHeight(settings['height'])\n        autoFillInHiResFixs(\n            settings['firstphase_width'],\n            settings['firstphase_height']\n        )\n        sd_tab_store.data.cfg = settings['cfg']\n        sd_tab_store.data.denoising_strength = settings['denoising_strength']\n        autoFillInSliderUi(\n            settings['hi_res_denoising_strength'],\n            'hrDenoisingStrength',\n            'hDenoisingStrength',\n            100\n        )\n        sd_tab_store.data.mask_blur = settings['mask_blur']\n        sd_tab_store.data.inpaint_full_res = settings['inpaint_at_full_res']\n        sd_tab_store.data.enable_hr = settings['hi_res_fix']\n        sd_tab_store.data.seed = String(settings['seed'])\n    } catch (e) {\n        console.warn(e)\n    }\n}\n////// End Reset Settings Button //////////\n\nfunction setMaskBlur(mask_blur) {\n    document.getElementById('slMaskBlur').value = mask_blur\n}\n\nfunction getPromptShortcut() {\n    //read json string\n    //converted into json object\n    const prompt_shortcut_string =\n        document.getElementById('taPromptShortcut').value\n    const prompt_shortcut = JSON.parse(prompt_shortcut_string)\n    return prompt_shortcut\n}\nfunction setPromptShortcut(prompt_shortcut) {\n    //prompt_shortcut is json object\n    //convert it into pretty json string and save it in the prompt shortcut textarea\n    var JSONInPrettyFormat = JSON.stringify(prompt_shortcut, undefined, 7)\n    document.getElementById('taPromptShortcut').value = JSONInPrettyFormat\n}\n\nfunction getMaskContent() {\n    return [...document.getElementsByClassName('rbMaskContent')].filter(\n        (e) => e.checked == true\n    )[0].value\n}\nfunction setMaskContent(value) {\n    try {\n        //assume the sampler_name is valid\n        //return the first\n        //convert htmlCollection into an array, then user filter to get the radio button with the value equals to sampler_name\n        const mask_content_element = [\n            ...document.getElementsByClassName('rbMaskContent'),\n        ].filter((e) => e.value == value)[0]\n        mask_content_element.checked = true\n        return mask_content_element\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction addHistoryButtonsHtml(img_html) {\n    // Create new container element\n    const container = document.createElement('div')\n\n    container.className = 'viewer-image-container'\n\n    const elem = document.getElementById('svg_sp_btn')\n    // Create a copy of it\n    const clone = elem.cloneNode(true)\n    const button = clone\n    button.style.display = null\n    button.removeAttribute('id')\n\n    button.setAttribute('title', 'place the image on the canvas')\n\n    // Create button element\n    // const button = document.createElement('sp-button');\n    button.className = 'viewer-image-button'\n    // button.innerHTML = \"Button\";\n\n    button.addEventListener('click', async () => {\n        //set init image event listener, use when settion is active\n        let image_path = img_html.dataset.path\n        const image_path_escape = image_path.replace(/\\o/g, '/o') //escape string \"\\o\" in \"\\output\"\n\n        // load the image from \"data:image/png;base64,\" base64_str\n        const base64_image = img_html.src.replace('data:image/png;base64,', '')\n        await base64ToFile(base64_image)\n    })\n\n    // Append elements to container\n    container.appendChild(img_html)\n    container.appendChild(button)\n\n    return container\n}\n\nfunction updateProgressBarsHtml(new_value, progress_text = 'Progress...') {\n    document.querySelectorAll('.pProgressBars').forEach((bar_elm) => {\n        // id = el.getAttribute(\"id\")\n        // console.log(\"progressbar id:\", id)\n        try {\n            bar_elm.setAttribute('value', new_value)\n            document\n                .querySelectorAll('.lProgressLabel')\n                .forEach((lable_elm) => {\n                    lable_elm.innerHTML = progress_text\n                    // else el.innerHTML = 'No work in progress'\n                })\n        } catch (e) {\n            console.warn(e) //value is not valid\n        }\n    })\n\n    // document.querySelector('#pProgressBar').value\n}\n///end selection mode////\n\nfunction isSquareThumbnail() {\n    return document.getElementById('chSquareThumbnail').checked\n}\n\nasync function populateMenu(\n    html_menu_id,\n    menu_item_class,\n    items,\n    createMenuItemHtml,\n    b_keep_old_selection = false,\n    label = ''\n) {\n    // function createMenuItemHtml(item, item_html_element) {\n    //     // menu_item_element.innerHTML = item.title\n    //     // menu_item_element.dataset.model_hash = model.hash\n    //     // menu_item_element.dataset.model_title = model.title\n    // }\n\n    try {\n        const html_menu_element = document.getElementById(html_menu_id)\n        html_menu_element.innerHTML = '' // empty the menu\n        if (label) {\n            const label_item = document.createElement('sp-menu-item')\n            label_item.selected = true\n            label_item.disabled = true\n            label_item.innerText = label\n            html_menu_element.appendChild(label_item)\n        }\n        for (let item of items) {\n            const menu_item_element = document.createElement('sp-menu-item')\n            menu_item_element.className = menu_item_class\n            createMenuItemHtml(item, menu_item_element)\n            html_menu_element.appendChild(menu_item_element)\n        }\n    } catch (e) {\n        b_result = false\n        console.warn(e)\n    }\n    return b_result\n}\nasync function populateMenuByElement(\n    html_menu_element,\n    menu_item_class,\n    items,\n    createMenuItemHtml,\n    b_keep_old_selection = false,\n    label = ''\n) {\n    // function createMenuItemHtml(item, item_html_element) {\n    //     // menu_item_element.innerHTML = item.title\n    //     // menu_item_element.dataset.model_hash = model.hash\n    //     // menu_item_element.dataset.model_title = model.title\n    // }\n\n    try {\n        html_menu_element.innerHTML = '' // empty the menu\n        if (label) {\n            const label_item = document.createElement('sp-menu-item')\n            label_item.selected = true\n            label_item.disabled = true\n            label_item.innerText = label\n            html_menu_element.appendChild(label_item)\n        }\n        for (let item of items) {\n            const menu_item_element = document.createElement('sp-menu-item')\n            menu_item_element.className = menu_item_class\n            createMenuItemHtml(item, menu_item_element)\n            html_menu_element.appendChild(menu_item_element)\n        }\n    } catch (e) {\n        b_result = false\n        console.warn(e)\n    }\n    return b_result\n}\nfunction getSelectedMenuItem(menu_id) {\n    try {\n        const menu_element = document.getElementById(menu_id)\n        return menu_element.selectedOptions[0]\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction getSelectedMenuItemByElement(menu_element) {\n    try {\n        // const menu_element = document.getElementById(menu_id)\n        return menu_element.selectedOptions[0]\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction selectMenuItem(menu_id, item) {\n    try {\n        const menu_element = document.getElementById(menu_id)\n        const option = Array.from(menu_element.options).filter(\n            (element) => element.value === item\n        )[0]\n        option.selected = true\n    } catch (e) {\n        unselectMenuItem(menu_id)\n        console.warn(e)\n    }\n}\nfunction selectMenuItemByElement(menu_element, item) {\n    try {\n        const option = Array.from(menu_element.options).filter(\n            (element) => element.value === item\n        )[0]\n\n        option.selected = true\n        // option.dispatchEvent(new Event('click'))\n        // option.click()\n    } catch (e) {\n        unselectMenuItemByElement(menu_element)\n        console.warn(e)\n    }\n}\nfunction getSelectedMenuItemTextContent(menu_id) {\n    try {\n        const selected_item = getSelectedMenuItem(menu_id)\n        if (selected_item.disabled === true) return '' // ignore the label item\n\n        const text_content = selected_item.textContent\n        return text_content\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction getSelectedMenuItemTextContentByElement(menu_element) {\n    try {\n        const selected_item = getSelectedMenuItemByElement(menu_element)\n        if (selected_item.disabled === true) return ''\n        const text_content = selected_item.textContent\n        return text_content\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction unselectMenuItem(menu_id) {\n    try {\n        document.getElementById(menu_id).selectedIndex = null\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction unselectMenuItemByElement(menu_element) {\n    try {\n        menu_element.selectedIndex = null\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction getUseNsfw() {\n    //this method is shared between horde native and horde script\n    const b_nsfw = document.getElementById('chUseNSFW').checked\n    return b_nsfw\n}\nfunction getUseSilentMode_Old() {\n    const b_use_silent_mode = document.getElementById('chUseSilentMode').checked\n    return b_use_silent_mode\n}\nfunction getUseSilentMode() {\n    let b_use_silent_mode = true //fast machine\n    const pc_speed = getSelectedRadioButtonElement('rbPCSpeed').value\n    if (pc_speed === 'slow') {\n        b_use_silent_mode = false // use noisy mode\n    } else if (pc_speed === 'fast') {\n        b_use_silent_mode = true // use silent mode\n    }\n    // const b_use_silent_mode = document.getElementById('chUseSilentMode').checked\n    return b_use_silent_mode\n}\n\nmodule.exports = {\n    autoFillInPrompt,\n\n    autoFillInNegativePrompt,\n\n    getWidth,\n    autoFillInWidth,\n    getHeight,\n    autoFillInHeight,\n    getSliderSdValue,\n    setSliderSdValue,\n    autoFillInHiResFixs,\n\n    autoFillInSliderUi,\n\n    autoFillInSampler,\n\n    setInitImageSrc,\n    setInitImageMaskSrc,\n\n    setAutomaticStatus,\n    setProxyServerStatus,\n\n    autoFillSettings,\n\n    setMaskBlur,\n\n    autoFillInHRHeight,\n    autoFillInHRWidth,\n    getPromptShortcut,\n    setPromptShortcut,\n    getModelHashByTitle,\n\n    autoFillInInpaintMaskWeight,\n\n    getBatchNumber,\n    autoFillInBatchNumber,\n    getHrWidth,\n    getHrHeight,\n    setCFG,\n    getCFG,\n    getMaskContent,\n    setMaskContent,\n    addHistoryButtonsHtml,\n\n    updateProgressBarsHtml,\n    getBackendType,\n    getHordeApiKey,\n    setProgressImageSrc,\n\n    isSquareThumbnail,\n    setControlImageSrc,\n\n    setHordeApiKey,\n    populateMenu,\n    getSelectedMenuItem,\n    getSelectedMenuItemTextContent,\n    getUseNsfw,\n    getUseSilentMode,\n    unselectMenuItem,\n    selectMenuItem,\n    getSliderSdValue_Old,\n    getSelectedRadioButtonElement,\n    getInitImageMaskElement,\n\n    getSliderSdValueByElement,\n    setSliderSdValueByElements,\n    populateMenuByElement,\n    selectMenuItemByElement,\n    unselectMenuItemByElement,\n    getSelectedMenuItemByElement,\n    getSelectedMenuItemTextContentByElement,\n}\n"
  },
  {
    "path": "utility/io.js",
    "content": "const psapi = require('../psapi')\n\nconst layer_util = require('../utility/layer')\nconst general = require('./general')\n\nconst { executeAsModal } = require('photoshop').core\nconst batchPlay = require('photoshop').action.batchPlay\nconst formats = require('uxp').storage.formats\nconst storage = require('uxp').storage\nconst fs = storage.localFileSystem\n\nasync function isBlackAndWhiteImage(base64EncodedImage) {\n    try {\n        // Load your base64 encoded image\n        const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))\n        console.log(\n            'isBlackAndWhiteImage(): image.bitmap.width, image.bitmap.height: ',\n            image.bitmap.width,\n            image.bitmap.height\n        )\n        // Check if your image only has one channel\n        return (\n            image.bitmap.width === image.bitmap.height &&\n            image.bitmap.width === 1\n        )\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function convertBlackAndWhiteImageToRGBChannels(base64EncodedImage) {\n    // Load your base64 encoded image\n    const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))\n\n    // Convert your black and white image to RGB channels\n    image.color([\n        { apply: 'red', params: [255] },\n        { apply: 'green', params: [255] },\n        { apply: 'blue', params: [255] },\n    ])\n\n    // Get your base64 encoded black and white image with RGB channels\n    const base64EncodedImageWithRGBChannels = await image.getBase64Async(\n        Jimp.MIME_JPEG\n    )\n\n    return base64EncodedImageWithRGBChannels\n}\nasync function convertBlackAndWhiteImageToRGBChannels2(base64EncodedImage) {\n    try {\n        // Load your base64 encoded image\n        const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))\n\n        // Convert your black and white image to RGB channels\n        image.color([{ apply: 'mix', params: ['#ffffff', 100] }])\n\n        // Get your base64 encoded black and white image with RGB channels\n        const base64EncodedImageWithRGBChannels = await image.getBase64Async(\n            Jimp.MIME_JPEG\n        )\n\n        return base64EncodedImageWithRGBChannels\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function convertBlackAndWhiteImageToRGBChannels3(base64EncodedImage) {\n    try {\n        // Load your base64 encoded image\n        const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))\n\n        // Convert your black and white image to RGB channels\n        // image.color([{ apply: 'mix', params: ['#ffffff', 100] }])\n\n        // Get your base64 encoded black and white image with RGB channels\n        const base64EncodedImageWithRGBChannels = await image.getBase64Async(\n            Jimp.MIME_PNG\n        )\n\n        return base64EncodedImageWithRGBChannels\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function snapShotLayer() {\n    //snapshot layer with no mask\n    let command = [\n        // Select All Layers current layer\n        {\n            _obj: 'selectAllLayers',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n        },\n        // Duplicate current layer\n        // {\"ID\":[459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513],\"_obj\":\"duplicate\",\"_target\":[{\"_enum\":\"ordinal\",\"_ref\":\"layer\",\"_value\":\"targetEnum\"}],\"version\":5},\n        {\n            // ID: ids,\n            _obj: 'duplicate',\n            _target: [\n                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },\n            ],\n            // version: 5\n        },\n\n        // Merge Layers\n        { _obj: 'mergeLayersNew' },\n        // Make\n        {\n            _obj: 'make',\n            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },\n            new: { _class: 'channel' },\n            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },\n        },\n        // Set Selection\n        {\n            _obj: 'set',\n            _target: [{ _property: 'selection', _ref: 'channel' }],\n            to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },\n        },\n        //make a group\n        {\n            _obj: 'make',\n            _target: [\n                {\n                    _ref: 'layerSection',\n                },\n            ],\n            from: {\n                _ref: 'layer',\n                _enum: 'ordinal',\n                _value: 'targetEnum',\n            },\n            layerSectionStart: 512,\n            layerSectionEnd: 513,\n            name: 'Group 2',\n            _options: {\n                dialogOptions: 'dontDisplay',\n            },\n        },\n        {\n            _obj: 'mergeLayersNew',\n            _options: {\n                dialogOptions: 'dontDisplay',\n            },\n        },\n    ]\n\n    const result = await batchPlay(command, {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n\n    return result\n}\n\nasync function snapShotLayerExe() {\n    await executeAsModal(async () => {\n        //create a fill layer above the background layer, so that it's present in the snapshot\n        try {\n            const selectionInfo = await psapi.getSelectionInfoExe()\n\n            // const backgroundLayer = await app.activeDocument.backgroundLayer\n\n            await psapi.createSolidLayer(255, 255, 255)\n            const solid_layer = await app.activeDocument.activeLayers[0]\n            // await psapi.unSelectMarqueeExe()//unselect the\n\n            // await solid_layer.moveAbove(backgroundLayer)\n            // await snapShotLayer() //create a layer with only the opaque pixels\n            // await psapi.reSelectMarqueeExe(selectionInfo)\n            // await solid_layer.delete()\n        } catch (e) {\n            console.warn(e)\n        }\n    })\n    await executeAsModal(async () => {\n        //create a fill layer above the background layer, so that it's present in the snapshot\n        try {\n            const solid_layer = await app.activeDocument.activeLayers[0]\n            const backgroundLayer = await app.activeDocument.backgroundLayer\n            await solid_layer.moveAbove(backgroundLayer)\n            await psapi.unselectActiveLayersExe()\n            await snapShotLayer() //create a layer with only the opaque pixels\n            // await psapi.reSelectMarqueeExe(selectionInfo)\n            // await psapi.unSelectMarqueeExe()//unselect the\n            await solid_layer.delete()\n        } catch (e) {\n            console.warn(e)\n        }\n    })\n}\n\nclass IO {\n    // constructor() {}\n    static async exportWebp(layer, export_width, export_height) {\n        await executeAsModal(async () => {\n            //we assume we have a valid layer rectangular image/layer, no transparency\n            const doc_entry = await getCurrentDocFolder() //get the main document folder before we switch doc\n            const layer_info = await layer_util.Layer.getLayerInfo(layer)\n            //*) create a new document\n            const new_doc = await IOHelper.createDocumentExe(\n                export_width,\n                export_height\n            )\n            const new_layer = await layer_util.Layer.duplicateToDoc(\n                layer,\n                new_doc\n            )\n            //*) resize the layer to the same dimension as the document\n\n            await layer_util.Layer.scaleTo(\n                new_layer,\n                new_doc.width,\n                new_doc.height\n            ) //\n\n            await layer_util.Layer.moveTo(new_layer, 0, 0) //move to the top left corner\n            //\n            await IOHelper.saveAsWebpExe(doc_entry) //save current document as .webp file, save it into doc_entry folder\n            await new_doc.closeWithoutSaving()\n        })\n    }\n    static async exportPng() {}\n    static async exportDoc() {}\n    static async exportLayer() {}\n\n    static async base64PngToPngFile(\n        base64_png,\n        folder,\n        image_name = 'temp_base64Png.png'\n    ) {\n        const arrayBuffer = _base64ToArrayBuffer(base64_png)\n\n        // const folder = await storage.localFileSystem.getTemporaryFolder()\n\n        const file = await folder.createFile(image_name, { overwrite: true })\n\n        await file.write(arrayBuffer, { format: storage.formats.binary })\n        return file\n    }\n    static async openImageFileAsDocument(file_entry) {\n        const new_doc = await app.open(file_entry)\n        return new_doc\n    }\n    static async base64PngToBase64Webp(base64_png) {\n        let base64_webp\n        try {\n            await executeAsModal(async () => {\n                try {\n                    const main_doc_entry = await getCurrentDocFolder()\n                    //save the base64_png to .png file\n                    const temp_folder = await fs.getTemporaryFolder()\n                    const png_file = await this.base64PngToPngFile(\n                        base64_png,\n                        temp_folder\n                    )\n\n                    //load the .png file as a layer in new document\n                    const new_doc = await this.openImageFileAsDocument(png_file)\n                    //save document as .webp\n                    const [_, webp_file] = await IOHelper.saveAsWebpExe(\n                        main_doc_entry\n                    ) //save current document as .webp file, save it into doc_entry folder\n                    await new_doc.closeWithoutSaving()\n                    //load/read the .webp file as an arraybuffer\n                    const ArrayBufferWebp = await webp_file.read({\n                        format: formats.binary,\n                    })\n\n                    //convert the arraybuffer to base64Webp string\n\n                    base64_webp = _arrayBufferToBase64(ArrayBufferWebp)\n                } catch (e) {\n                    console.warn(e)\n                }\n            })\n            return base64_webp\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async base64WebpFromFile(file_entry) {\n        //file_entry most be .webp\n        let webp_base64\n        try {\n            await executeAsModal(async () => {\n                const arrayBuffer = await file_entry.read({\n                    format: formats.binary,\n                })\n                console.log('webp arrayBuffer:', arrayBuffer)\n\n                const base64_image = _arrayBufferToBase64(arrayBuffer) //convert the buffer to base64\n                console.log('base64_image:', base64_image)\n                webp_base64 = base64_image\n            })\n            return [webp_base64, webp_arrayBuffer]\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    static async base64ToLayer(\n        base64_png,\n        image_name = 'base64_to_layer.png',\n        to_x = 0,\n        to_y = 0,\n        width = 512,\n        height = 512,\n        format = 'png'\n    ) {\n        let layer\n        if (format === 'png') {\n            try {\n                await executeAsModal(async (context) => {\n                    // let history_id\n                    // try {\n                    //     history_id = await context.hostControl.suspendHistory({\n                    //         documentID: app.activeDocument.id,\n                    //         name: 'Place Image',\n                    //     })\n                    // } catch (e) {\n                    //     console.warn(e)\n                    // }\n\n                    layer = await IOBase64ToLayer.base64PngToLayer(\n                        base64_png,\n                        image_name\n                    )\n\n                    await psapi.setVisibleExe(layer, true)\n                    await layer_util.Layer.scaleTo(layer, width, height) //\n                    await layer_util.Layer.moveTo(layer, to_x, to_y) //move to the top left corner\n                    await psapi.setVisibleExe(layer, true)\n\n                    // try {\n                    //     await context.hostControl.resumeHistory(history_id)\n                    // } catch (e) {\n                    //     console.warn(e)\n                    // }\n                })\n            } catch (e) {\n                console.warn(e)\n            }\n        }\n        return layer\n    }\n\n    static async getSelectionFromCanvasAsBase64Silent(\n        selectionInfo,\n        b_resize = false,\n        resize_width = 0,\n        resize_height = 0\n    ) {\n        //it will save the document then crop it so that only the selection area are left.\n        //return arrayBuffer or base64Png?\n        try {\n            let file\n            const folder = await fs.getTemporaryFolder()\n            await executeAsModal(\n                async () => {\n                    const canvas_image_name = 'canvas_image.png'\n                    file = await folder.createFile(canvas_image_name, {\n                        overwrite: true,\n                    })\n\n                    const currentDocument = app.activeDocument\n                    await currentDocument.saveAs.png(file, null, true)\n                    //save file end\n\n                    //read the saved image.png\n                },\n\n                { commandName: 'readPng' }\n            )\n\n            const arrayBuffer = await file.read({\n                format: formats.binary,\n            })\n\n            // const selectionInfo = g_generation_session.selectionInfo\n            // const selectionInfo = await psapi.getSelectionInfoExe()\n            const cropped_base64_url = await IOHelper.cropPng(\n                arrayBuffer,\n                selectionInfo,\n                true,\n                resize_width,\n                resize_height\n            )\n            const cropped_base64 = general.base64UrlToBase64(cropped_base64_url)\n\n            // html_manip.setInitImageSrc(cropped_base64_url)\n            return cropped_base64\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async getSelectionFromCanvasAsBase64NonSilent(\n        layer,\n        image_name,\n        width,\n        height\n    ) {\n        try {\n            const image_buffer = await psapi.newExportPng(\n                layer,\n                image_name,\n                width,\n                height\n            )\n\n            const base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64\n            //send the base64 to the server to save the file in the desired directory\n            // await sdapi.requestSavePng(base64_image, image_name)\n            // await saveFileInSubFolder(base64_image, document_name, image_name)\n\n            const { requestSavePng } = require('../sdapi_py_re')\n            await requestSavePng(base64_image, image_name)\n            return base64_image\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async getSelectionFromCanvasAsBase64Interface(\n        width,\n        height,\n        layer,\n        selectionInfo,\n        resize = true,\n        use_silent_mode = true,\n        image_name = 'temp.png'\n    ) {\n        let base64_image\n        if (use_silent_mode) {\n            base64_image = await this.getSelectionFromCanvasAsBase64Silent(\n                selectionInfo,\n                resize,\n                width,\n                height\n            )\n        } else {\n            base64_image = await this.getSelectionFromCanvasAsBase64NonSilent(\n                layer,\n                image_name,\n                width,\n                height\n            )\n        }\n        return base64_image\n    }\n    static async getSelectionFromCanvasAsBase64Interface_New(\n        width,\n        height,\n        selectionInfo,\n        resize = true,\n        image_name = 'temp.png'\n    ) {\n        //use this version, it has less parameters\n        const use_silent_mode = html_manip.getUseSilentMode()\n        let layer = null\n        if (!use_silent_mode) {\n            await psapi.snapshot_layerExe()\n            const snapshotLayer = await app.activeDocument.activeLayers[0]\n            layer = snapshotLayer\n        }\n        let base64_image\n        if (use_silent_mode) {\n            base64_image = await this.getSelectionFromCanvasAsBase64Silent(\n                selectionInfo,\n                resize,\n                width,\n                height\n            )\n        } else {\n            base64_image = await this.getSelectionFromCanvasAsBase64NonSilent(\n                layer,\n                image_name,\n                width,\n                height\n            )\n        }\n        await layer_util.deleteLayers([layer]) //delete the snapshot layer if it exists\n        return base64_image\n    }\n\n    static async urlToLayer(image_url, image_file_name = 'image_from_url.png') {\n        try {\n            await psapi.unselectActiveLayersExe()\n            const temp_entry = await fs.getTemporaryFolder()\n            await downloadItExe(image_url, temp_entry, image_file_name)\n        } catch (e) {\n            console.warn('urlToLayer()', image_url, image_file_name, e)\n        }\n    }\n}\n\nclass IOHelper {\n    static async saveAsWebp(doc_entry) {\n        //doc_entry must be in dataFolder or tempFolder\n        //save document as webp\n        const document_id = app.activeDocument.id\n\n        // doc_entry = await getCurrentDocFolder()\n        const file_entry = await doc_entry.createFile('temp.webp', {\n            overwrite: true,\n        })\n\n        const token = await fs.createSessionToken(file_entry)\n        const result = await batchPlay(\n            [\n                {\n                    _obj: 'save',\n                    as: {\n                        _obj: 'WebPFormat',\n                        compression: {\n                            _enum: 'WebPCompression',\n                            _value: 'compressionLossless',\n                        },\n                        includeXMPData: false,\n                        includeEXIFData: false,\n                        includePsExtras: false,\n                    },\n                    in: {\n                        _path: token,\n                        _kind: 'local',\n                    },\n                    documentID: 59,\n                    copy: true,\n                    lowerCase: true,\n                    saveStage: {\n                        _enum: 'saveStageType',\n                        _value: 'saveBegin',\n                    },\n                    _options: {\n                        dialogOptions: 'dontDisplay',\n                    },\n                },\n            ],\n            {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            }\n        )\n\n        return [result, file_entry]\n    }\n\n    static async saveAsWebpExe(doc_entry) {\n        let result\n        let file_entry\n        await executeAsModal(async () => {\n            ;[result, file_entry] = await this.saveAsWebp(doc_entry)\n        })\n        return [result, file_entry]\n    }\n    static async createDocumentExe(width, height) {\n        let new_doc\n        try {\n            await executeAsModal(async () => {\n                new_doc = await app.documents.add({\n                    width: width,\n                    height: height,\n                    resolution: await app.activeDocument.resolution,\n                    mode: 'RGBColorMode',\n                    fill: 'transparent',\n                })\n            })\n        } catch (e) {\n            console.warn(e)\n        }\n        return new_doc\n    }\n    static async cropPng(\n        arrayBuffer,\n        selectionInfo,\n        b_resize = false,\n        resize_width = 0,\n        resize_height = 0\n    ) {\n        //crop png from array buffer\n        //have the option to resize the after cropping\n\n        const crop_x = selectionInfo.left\n        const crop_y = selectionInfo.top\n        const crop_w = selectionInfo.width\n        const crop_h = selectionInfo.height\n        const base64_url_result = await Jimp.read(arrayBuffer)\n            .then(async (img) => {\n                let cropped_img = await img.crop(\n                    crop_x,\n                    crop_y,\n                    crop_w,\n                    crop_h\n                    // crop_w - 1,\n                    // crop_h - 1\n                )\n\n                let resized_img\n                if (b_resize) {\n                    resized_img = await cropped_img.resize(\n                        resize_width,\n                        resize_height,\n                        // Jimp.RESIZE_BILINEAR\n                        // Jimp.RESIZE_NEAREST_NEIGHBOR\n                        settings_tab_ts.store.data.scale_interpolation_method\n                            .jimp\n                    )\n                } else {\n                    resized_img = cropped_img\n                }\n\n                const base64_url = await resized_img.getBase64Async(\n                    Jimp.MIME_PNG\n                )\n\n                // console.log('jimp: base64_url: ', base64_url)\n                // document.getElementById(\"image\").setAttribute(\"src\", data);\n\n                return base64_url\n            })\n            .catch((error) => {\n                console.error(error)\n            })\n        return base64_url_result\n    }\n}\n\nclass IOBase64ToLayer {\n    static {}\n    static async base64PngToLayer(base64_png, image_name) {\n        //unselect all layers so that the imported layer get place at the top of the document\n        await psapi.unselectActiveLayersExe()\n\n        const imported_layer = await base64ToFile(base64_png, image_name) //silent import into the document\n\n        return imported_layer\n    }\n}\nclass IOFolder {\n    static {}\n    static async createSettingsFolder() {\n        //create a folder named \"Settings\" in the DataFolder\n        let settings_entry\n        await executeAsModal(async () => {\n            settings_entry = await this.createFolderSafe('Settings')\n        })\n        return settings_entry\n    }\n    static async findOrCreateFolderExe(folder_name) {\n        //create a folder named \"Settings\" in the DataFolder\n        let folder_entry\n        await executeAsModal(async () => {\n            folder_entry = await this.createFolderSafe(folder_name)\n        })\n        return folder_entry\n    }\n\n    static async doesFolderExist(folder_name) {\n        //check if folder exist. return true if it does. false if it doesn't.\n        const data_folder = await fs.getDataFolder()\n        let b_exist = false\n        let folder\n        try {\n            folder = await data_folder.getEntry(folder_name)\n            b_exist = true\n        } catch (e) {\n            // console.warn(e)\n            b_exist = false\n        }\n        return b_exist\n    }\n\n    static async createFolderSafe(folder_name) {\n        //will always return a folder. it will create the folder if it doesn't exist.\n        try {\n            // const uuid = await getUniqueDocumentId()\n            const data_folder = await fs.getDataFolder()\n\n            let folder_entry\n            try {\n                folder_entry = await data_folder.getEntry(folder_name)\n            } catch (e) {\n                console.warn(e)\n                //create document folder\n                folder_entry = await data_folder.createFolder(folder_name)\n            }\n\n            return folder_entry\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    static async getDocumentFolderNativePath() {\n        try {\n            const uuid = await getUniqueDocumentId()\n\n            let doc_folder = await this.getDocFolder(uuid)\n            const path = general.fixNativePath(doc_folder.nativePath)\n            return path\n        } catch (e) {\n            console.warn(e)\n        }\n        return ''\n    }\n\n    static async getDocFolder(doc_uuid) {\n        //will create folder if does not exist. always return a folder entry\n        const doc_entry = await getDocFolder(doc_uuid)\n        return doc_entry\n    }\n    static async getSettingsFolder() {\n        //will create folder if does not exist. always return a folder entry\n        const settings_entry = await this.createSettingsFolder()\n        return settings_entry\n    }\n    static async getPresetFolder() {\n        //will create folder if does not exist. always return a folder entry\n        const preset_entry = await this.findOrCreateFolderExe('Preset')\n        return preset_entry\n    }\n    static async getCustomPresetFolder(\n        custom_preset_folder_name = 'custom_preset'\n    ) {\n        //will create folder if does not exist. always return a folder entry\n        const preset_entry = await this.findOrCreateFolderExe(\n            custom_preset_folder_name\n        )\n        return preset_entry\n    }\n    static async createFolderIfDoesNotExist(folder_name) {\n        try {\n            await executeAsModal(async () => {\n                try {\n                    const folder = await fs.getDataFolder()\n                    const sub_folder = await folder.createFolder(folder_name)\n                } catch (e) {\n                    console.warn(e)\n                }\n            })\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\n\nclass IOLog {\n    static {}\n    static async saveLogToFile(json, file_name) {\n        try {\n            const plugin_folder = await fs.getDataFolder()\n            const file = await plugin_folder.createFile(file_name, {\n                type: storage.types.file,\n                overwrite: true,\n            })\n\n            const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)\n            await file.write(JSONInPrettyFormat, {\n                format: storage.formats.utf8,\n                append: true,\n            })\n        } catch (e) {\n            _warn(e)\n        }\n    }\n}\nclass IOJson {\n    static {}\n    static async saveJsonToFile(json, folder_entry, file_name) {\n        try {\n            const file = await folder_entry.createFile(file_name, {\n                type: storage.types.file,\n                overwrite: true,\n            })\n\n            const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)\n            await file.write(JSONInPrettyFormat, {\n                format: storage.formats.utf8,\n                append: false,\n            })\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    static async saveJsonToFileExe(json, folder_entry, file_name) {\n        await executeAsModal(async () => {\n            await this.saveJsonToFile(json, folder_entry, file_name)\n        })\n    }\n    static async loadJsonFromFile(folder_entry, file_name) {\n        const json_file_name = file_name\n\n        try {\n            const json_entry = await folder_entry.getEntry(json_file_name)\n            if (json_entry) {\n                const json = JSON.parse(\n                    await json_entry.read({\n                        format: storage.formats.utf8,\n                    })\n                )\n                return json\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    static async saveSettingsToFile(settings_json, settings_file_name) {\n        await executeAsModal(async () => {\n            const folder_entry = await IOFolder.getSettingsFolder('Settings')\n            await this.saveJsonToFile(\n                settings_json,\n                folder_entry,\n                settings_file_name\n            )\n        })\n    }\n    static async loadSettingsFromFile(settings_file_name) {\n        const folder_entry = await IOFolder.getSettingsFolder('Settings')\n        const settings_json = await this.loadJsonFromFile(\n            folder_entry,\n            settings_file_name\n        )\n        return settings_json\n    }\n    static async loadSessionIDFromFile(uuid) {\n        try {\n            // const uuid = await getUniqueDocumentId()\n            const doc_entry = await getDocFolder(uuid)\n            const json_data = await this.loadJsonFromFile(\n                doc_entry,\n                'session_id.json'\n            )\n            return json_data?.session_id ?? 0\n        } catch (e) {\n            console.error(e)\n        }\n    }\n    static async saveSessionID(session_id, uuid) {\n        const doc_entry = await getDocFolder(uuid)\n\n        await executeAsModal(async () => {\n            await this.saveJsonToFile(\n                { session_id: session_id },\n                doc_entry,\n                'session_id.json'\n            )\n        })\n    }\n\n    static async saveHordeSettingsToFile(settings_json) {\n        const settings_file_name = 'horde_settings.json'\n        await this.saveSettingsToFile(settings_json, settings_file_name)\n    }\n    static async loadHordeSettingsFromFile() {\n        const settings_file_name = 'horde_settings.json'\n        const settings_json = await this.loadSettingsFromFile(\n            settings_file_name\n        )\n        return settings_json\n    }\n\n    static async getJsonEntries(doc_entry) {\n        let entries = await doc_entry.getEntries()\n        const json_entries = entries.filter(\n            (e) => e.isFile && e.name.toLowerCase().includes('.json') // must be a file and has the of the type .json\n        )\n        console.log('json_entries: ', json_entries)\n        // .forEach((e) => console.log(e.name))\n        return json_entries\n    }\n    static async deleteFile(doc_entry, file_name) {\n        try {\n            const file_entry = await doc_entry.getEntry(file_name)\n            file_entry.delete()\n        } catch (e) {}\n    }\n}\n\nasync function createThumbnail(base64Image, width = 100) {\n    const image = await Jimp.read(Buffer.from(base64Image, 'base64'))\n    image.resize(\n        width,\n        Jimp.AUTO,\n        settings_tab_ts.store.data.scale_interpolation_method.jimp\n    )\n    const thumbnail = await image.getBase64Async(Jimp.MIME_PNG)\n    return thumbnail\n}\n\nasync function getImageFromCanvas(scale_to_sliders = true) {\n    let width\n    let height\n    const selectionInfo = await psapi.getSelectionInfoExe()\n    if (scale_to_sliders) {\n        width = html_manip.getWidth()\n        height = html_manip.getHeight()\n    } else {\n        width = selectionInfo.width\n        height = selectionInfo.height\n    }\n    const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(\n        width,\n        height,\n        selectionInfo,\n        true\n    )\n    return base64\n}\nasync function getBase64FromJimp(jimp_image) {\n    const dataURL = await jimp_image.getBase64Async(Jimp.MIME_PNG)\n    const base64 = dataURL.replace(/^data:image\\/png;base64,/, '')\n    return base64\n}\n\nfunction transparentToMask(x, y, idx) {\n    const alpha = this.bitmap.data[idx + 3]\n    let color\n    if (alpha === 0) {\n        color = 0xffffffff\n    } else if (alpha === 255) {\n        color = 0x000000ff\n    } else {\n        color = Jimp.rgbaToInt(alpha, alpha, alpha, 255)\n    }\n    this.setPixelColor(color, x, y)\n}\nfunction inpaintTransparentToMask(x, y, idx) {\n    const alpha = this.bitmap.data[idx + 3]\n    let color\n    // if (alpha === 0) {\n    //     color = 0x000000ff\n    // } else if (alpha === 255) {\n    //     color = 0xffffffff\n    // } else {\n    //     color = Jimp.rgbaToInt(alpha, alpha, alpha, 255)\n    // }\n\n    if (alpha === 0) {\n        color = 0x000000ff\n    } else {\n        color = 0xffffffff\n    }\n    this.setPixelColor(color, x, y)\n}\nfunction transparentToWhiteBackground(x, y, idx) {\n    const alpha = this.bitmap.data[idx + 3]\n    let color\n    if (alpha === 0) {\n        color = 0xffffffff\n    } else {\n        color = Jimp.rgbaToInt(\n            this.bitmap.data[idx],\n            this.bitmap.data[idx + 1],\n            this.bitmap.data[idx + 2],\n            255\n        ) // remove transparency but keep the color, This is bad. used as workaround Auto1111 not able to handle alpha channels\n    }\n    this.setPixelColor(color, x, y)\n}\nasync function getMask() {\n    try {\n        let b = app.activeDocument.backgroundLayer\n        await executeAsModal(() => (b.visible = false))\n        const base64 = await getImageFromCanvas()\n        await executeAsModal(() => (b.visible = true))\n        const jimp_image = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        const jimp_mask = await jimp_image.scan(\n            0,\n            0,\n            jimp_image.bitmap.width,\n            jimp_image.bitmap.height,\n            transparentToMask\n        )\n        html_manip.setInitImageSrc(\n            await jimp_mask.getBase64Async(Jimp.MIME_PNG)\n        )\n        const mask = await getBase64FromJimp(jimp_mask)\n        return mask\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function getImg2ImgInitImage() {\n    //the init image will has transparent pixel in it\n    //the mask will be a grayscale image/white and black\n    try {\n        let b = app.activeDocument.backgroundLayer\n        await executeAsModal(() => (b.visible = false))\n        const base64 = await getImageFromCanvas()\n        await executeAsModal(() => (b.visible = true))\n        const init_image = base64\n\n        html_manip.setInitImageSrc(general.base64ToBase64Url(init_image)) // convert jimp_image to img.src data\n\n        // console.log('mask: ', mask)\n        return init_image\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function getOutpaintInitImageAndMask() {\n    //the init image will has transparent pixel in it\n    //the mask will be a grayscale image/white and black\n    try {\n        let b = app.activeDocument.backgroundLayer\n        await executeAsModal(() => (b.visible = false))\n        const base64 = await getImageFromCanvas()\n        await executeAsModal(() => (b.visible = true))\n        const init_image = base64\n        let jimp_init = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        let jimp_mask = await jimp_init\n            .clone()\n            .scan(\n                0,\n                0,\n                jimp_init.bitmap.width,\n                jimp_init.bitmap.height,\n                transparentToMask\n            )\n        // jimp_init = await jimp_init.scan(\n        //     0,\n        //     0,\n        //     jimp_init.bitmap.width,\n        //     jimp_init.bitmap.height,\n        //     transparentToWhiteBackground\n        //     // transparentToMask\n        // )\n        html_manip.setInitImageMaskSrc(\n            await jimp_mask.getBase64Async(Jimp.MIME_PNG)\n        ) // convert jimp_image to img.src data\n        html_manip.setInitImageSrc(\n            await jimp_init.getBase64Async(Jimp.MIME_PNG)\n        ) // convert jimp_image to img.src data\n\n        const mask = await getBase64FromJimp(jimp_mask)\n        // console.log('mask: ', mask)\n        return {\n            init_image,\n            mask,\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\n//generate black and white mask image from\nasync function getMaskFromCanvas() {\n    try {\n        await executeAsModal(async () => await layer_util.toggleActiveLayer()) //only white mark layer should be visible\n        let mask_base64 = await getImageFromCanvas()\n        await executeAsModal(async () => {\n            await layer_util.toggleActiveLayer() // undo the toggling operation, active layer will be visible\n            app.activeDocument.activeLayers[0].visible = false //hide the white mark\n        })\n        let jimp_mask = await Jimp.read(Buffer.from(mask_base64, 'base64')) //make jimp object\n        jimp_mask = await jimp_mask.scan(\n            0,\n            0,\n            jimp_mask.bitmap.width,\n            jimp_mask.bitmap.height,\n            inpaintTransparentToMask\n        ) //convert transparent image to black and white image\n        mask_base64 = await getBase64FromJimp(jimp_mask)\n        return mask_base64\n    } catch (e) {\n        warn(e)\n    }\n}\nasync function getInpaintInitImageAndMask() {\n    try {\n        await executeAsModal(async () => await layer_util.toggleActiveLayer()) //only white mark layer should be visible\n        const mask_base64 = await getImageFromCanvas()\n        await executeAsModal(async () => {\n            await layer_util.toggleActiveLayer() // undo the toggling operation, active layer will be visible\n            app.activeDocument.activeLayers[0].visible = false //hide the white mark\n        })\n        const init_base64 = await getImageFromCanvas()\n\n        let jimp_mask = await Jimp.read(Buffer.from(mask_base64, 'base64')) //make jimp object\n        let jimp_init = await Jimp.read(Buffer.from(init_base64, 'base64')) //make jimp object, jimp_init will have transparent pixels, should we convert to white??\n\n        jimp_mask = await jimp_mask.scan(\n            0,\n            0,\n            jimp_mask.bitmap.width,\n            jimp_mask.bitmap.height,\n            inpaintTransparentToMask\n        ) //convert transparent image to black and white image\n\n        html_manip.setInitImageMaskSrc(\n            await jimp_mask.getBase64Async(Jimp.MIME_PNG)\n        )\n        html_manip.setInitImageSrc(\n            await jimp_init.getBase64Async(Jimp.MIME_PNG)\n        )\n\n        const mask = await getBase64FromJimp(jimp_mask)\n        const init_image = await getBase64FromJimp(jimp_init)\n        return { init_image, mask }\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function saveFileInSubFolder(b64Image, sub_folder_name, file_name) {\n    // const b64Image =\n    //     'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'\n\n    const img = _base64ToArrayBuffer(b64Image)\n\n    // const img_name = 'temp_output_image.png'\n    const img_name = file_name\n    const folder = await storage.localFileSystem.getDataFolder()\n    const documentFolderName = sub_folder_name\n    let documentFolder\n    try {\n        documentFolder = await folder.getEntry(documentFolderName)\n    } catch (e) {\n        console.warn(e)\n        //create document folder\n        documentFolder = await folder.createFolder(documentFolderName)\n    }\n\n    console.log('documentFolder.nativePath: ', documentFolder.nativePath)\n    const file = await documentFolder.createFile(img_name, { overwrite: true })\n\n    await file.write(img, { format: storage.formats.binary })\n\n    const token = await storage.localFileSystem.createSessionToken(file) // batchPlay requires a token on _path\n}\n//REFACTOR: move to document.js\nasync function saveJsonFileInSubFolder(json, sub_folder_name, file_name) {\n    // const b64Image =\n    //     'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'\n\n    // const img_name = 'temp_output_image.png'\n\n    const json_file_name = file_name\n\n    const folder = await storage.localFileSystem.getDataFolder()\n    const documentFolderName = sub_folder_name\n    let documentFolder\n    try {\n        documentFolder = await folder.getEntry(documentFolderName)\n    } catch (e) {\n        console.warn(e)\n        //create document folder\n        documentFolder = await folder.createFolder(documentFolderName)\n    }\n\n    console.log('documentFolder.nativePath: ', documentFolder.nativePath)\n    const file = await documentFolder.createFile(json_file_name, {\n        type: storage.types.file,\n        overwrite: true,\n    })\n\n    const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)\n    await file.write(JSONInPrettyFormat, {\n        format: storage.formats.utf8,\n        append: false,\n    })\n\n    const token = await storage.localFileSystem.createSessionToken(file) // batchPlay requires a token on _path\n}\nasync function fixTransparentEdges(base64) {\n    function transparentToOpaque(x, y, idx) {\n        const alpha = this.bitmap.data[idx + 3]\n        if (alpha > 0 && alpha < 255) {\n            this.bitmap.data[idx + 3] = 0 //make semi transparent pixels completely transparent\n        }\n    }\n\n    try {\n        let jimp_img = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        jimp_img = await jimp_img.scan(\n            0,\n            0,\n            jimp_img.bitmap.width,\n            jimp_img.bitmap.height,\n            transparentToOpaque\n        )\n        const opaque_base64 = await getBase64FromJimp(jimp_img)\n        return opaque_base64\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function maskFromInitImage(base64) {\n    function setTransparentToBlack(x, y, idx) {\n        let alpha = this.bitmap.data[idx + 3]\n        if (alpha !== 0) {\n            this.bitmap.data[idx] = 0\n            this.bitmap.data[idx + 1] = 0\n            this.bitmap.data[idx + 2] = 0\n            this.bitmap.data[idx + 3] = 255\n        } else {\n            //alpha === 0\n\n            this.bitmap.data[idx] = 255\n            this.bitmap.data[idx + 1] = 255\n            this.bitmap.data[idx + 2] = 255\n            this.bitmap.data[idx + 3] = 255\n        }\n    }\n\n    try {\n        let jimp_img = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        jimp_img = await jimp_img.scan(\n            0,\n            0,\n            jimp_img.bitmap.width,\n            jimp_img.bitmap.height,\n            setTransparentToBlack\n        )\n        const mask_base64 = await getBase64FromJimp(jimp_img)\n        return mask_base64\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function fixMaskEdges(base64) {\n    function grayScaleToBlack(x, y, idx) {\n        if (\n            this.bitmap.data[idx] !== 255 ||\n            this.bitmap.data[idx + 1] !== 255 ||\n            this.bitmap.data[idx + 2] !== 255\n        ) {\n            this.bitmap.data[idx] = 0\n            this.bitmap.data[idx + 1] = 0\n            this.bitmap.data[idx + 2] = 0\n        }\n    }\n\n    try {\n        let jimp_img = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        jimp_img = await jimp_img.scan(\n            0,\n            0,\n            jimp_img.bitmap.width,\n            jimp_img.bitmap.height,\n            grayScaleToBlack\n        )\n        const opaque_base64 = await getBase64FromJimp(jimp_img)\n        return opaque_base64\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function getUniqueDocumentId() {\n    try {\n        let uniqueDocumentId = await psapi.readUniqueDocumentIdExe()\n\n        console.log(\n            'getUniqueDocumentId():  uniqueDocumentId: ',\n            uniqueDocumentId\n        )\n\n        // Regular expression to check if string is a valid UUID\n        const regexExp =\n            /^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$/gi\n\n        // String with valid UUID separated by dash\n        // const str = 'a24a6ea4-ce75-4665-a070-57453082c256'\n\n        const isValidId = regexExp.test(uniqueDocumentId) // true\n        console.log('isValidId: ', isValidId)\n        if (isValidId == false) {\n            let uuid = self.crypto.randomUUID()\n            console.log(uuid) // for example \"36b8f84d-df4e-4d49-b662-bcde71a8764f\"\n            await psapi.saveUniqueDocumentIdExe(uuid)\n            uniqueDocumentId = uuid\n        }\n        return uniqueDocumentId\n    } catch (e) {\n        console.warn('warning Document Id may not be valid', e)\n    }\n}\nasync function getImageSize(base64) {\n    const image = await Jimp.read(Buffer.from(base64, 'base64'))\n    const width = image.bitmap.width\n    const height = image.bitmap.height\n    return { width, height }\n}\nasync function convertGrayscaleToMonochrome(base64) {\n    function grayToMonoPixel(x, y, idx) {\n        // convert any grayscale value to white, resulting in black and white image\n\n        // if (this.bitmap.data[idx] > 0) {\n        //     this.bitmap.data[idx] = 255\n        // }\n        // if (this.bitmap.data[idx + 1] > 0) {\n        //     this.bitmap.data[idx + 1] = 255\n        // }\n        // if (this.bitmap.data[idx + 2] > 0) {\n        //     this.bitmap.data[idx + 2] = 255\n        // }\n        let color\n        if (\n            this.bitmap.data[idx] !== 0 &&\n            this.bitmap.data[idx + 1] !== 0 &&\n            this.bitmap.data[idx + 2] !== 0\n        ) {\n            color = 0xffffffff\n        } else {\n            color = 0x000000ff\n        }\n        this.setPixelColor(color, x, y)\n    }\n    try {\n        const jimp_image = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        const jimp_mask = await jimp_image.scan(\n            0,\n            0,\n            jimp_image.bitmap.width,\n            jimp_image.bitmap.height,\n            grayToMonoPixel\n        )\n        const base64_monochrome_mask = await getBase64FromJimp(jimp_mask)\n        return base64_monochrome_mask\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function convertBlackToTransparentKeepBorders(\n    base64,\n    b_borders_or_corners = enum_ts.MaskModeEnum.Transparent // false for borders, true for corners\n) {\n    try {\n        let jimp_mask = await Jimp.read(Buffer.from(base64, 'base64'))\n\n        const width = jimp_mask.bitmap.width\n        const height = jimp_mask.bitmap.height\n        jimp_mask = await jimp_mask.scan(\n            0,\n            0,\n            width,\n            height,\n            function (x, y, idx) {\n                if (b_borders_or_corners === enum_ts.MaskModeEnum.Borders) {\n                    // keep borders\n                    if (\n                        x === 0 ||\n                        y === 0 ||\n                        x === width - 1 ||\n                        y === height - 1\n                    )\n                        return\n                } else if (\n                    b_borders_or_corners === enum_ts.MaskModeEnum.Corners\n                ) {\n                    // keep corners\n                    if (\n                        (x === 0 && y === 0) ||\n                        (x === 0 && y === height - 1) ||\n                        (x === width - 1 && y === 0) ||\n                        (x === width - 1 && y === height - 1)\n                    )\n                        return\n                }\n\n                const red = this.bitmap.data[idx + 0]\n                const green = this.bitmap.data[idx + 1]\n                const blue = this.bitmap.data[idx + 2]\n                if (red === 0 && green === 0 && blue === 0) {\n                    this.bitmap.data[idx + 3] = 0\n                }\n            }\n        )\n        const base64_mask = await getBase64FromJimp(jimp_mask)\n        return base64_mask\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function deleteFileIfLargerThan(file_name, size_mb = 200) {\n    // const file = await fs.getEntry('path/to/file.txt')\n    try {\n        const plugin_folder = await fs.getDataFolder()\n        try {\n            var file = await plugin_folder.getEntry(file_name)\n        } catch (e) {\n            _warn(e)\n        }\n        if (file) {\n            const contents = await file.read({ format: storage.formats.binary })\n            //  storage.formats.utf8\n            const fileSizeInBytes = contents.byteLength\n            const fileSizeInMegabytes = fileSizeInBytes / (1024 * 1024)\n\n            if (fileSizeInMegabytes > size_mb) {\n                await fs.removeEntry(file)\n            }\n        }\n    } catch (e) {\n        // console.warn(e)\n        _warn(e)\n    }\n}\nmodule.exports = {\n    IO,\n    snapShotLayerExe,\n    IOHelper,\n    IOJson,\n    IOFolder,\n    IOLog,\n    convertBlackAndWhiteImageToRGBChannels,\n    convertBlackAndWhiteImageToRGBChannels2,\n    convertBlackAndWhiteImageToRGBChannels3,\n    isBlackAndWhiteImage,\n    createThumbnail,\n    getMask,\n    getOutpaintInitImageAndMask,\n    getInpaintInitImageAndMask,\n    getImg2ImgInitImage,\n    saveFileInSubFolder,\n    saveJsonFileInSubFolder,\n    fixTransparentEdges,\n    fixMaskEdges,\n    maskFromInitImage,\n    getImageFromCanvas,\n    getUniqueDocumentId,\n    getImageSize,\n    convertGrayscaleToMonochrome,\n    deleteFileIfLargerThan,\n    getMaskFromCanvas,\n    convertBlackToTransparentKeepBorders,\n}\n"
  },
  {
    "path": "utility/layer.js",
    "content": "const { batchPlay } = require('photoshop').action\nconst { executeAsModal } = require('photoshop').core\nconst {\n    cleanLayers,\n    getLayerIndex,\n    selectLayers,\n    unSelectMarqueeCommand,\n    unSelectMarqueeExe,\n    getSelectionInfoExe,\n    reSelectMarqueeExe,\n} = require('../psapi')\n\nconst psapi = require('../psapi')\n// const Jimp = require('../jimp/browser/lib/jimp.min')\n// const { settings_tab_ts } = require('../typescripts/dist/bundle')\nconst constants = require('photoshop').constants\n\nasync function createNewLayerExe(layerName, opacity = 100) {\n    await executeAsModal(async () => {\n        await createNewLayerCommand(layerName, opacity)\n    })\n    const new_layer = await app.activeDocument.activeLayers[0]\n    return new_layer\n}\n\nasync function createNewLayerCommand(layerName, opacity = 100) {\n    return await app.activeDocument.createLayer({\n        name: layerName,\n        opacity: opacity,\n        mode: 'normal',\n    })\n}\n\nasync function deleteLayers(layers) {\n    try {\n        await cleanLayers(layers)\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function getIndexCommand() {\n    const command = {\n        _obj: 'get',\n        _target: [\n            {\n                _property: 'itemIndex',\n            },\n            {\n                _ref: 'layer',\n                _enum: 'ordinal',\n                _value: 'targetEnum',\n            },\n        ],\n    }\n    const result = await batchPlay([command], {\n        synchronousExecution: true,\n        modalBehavior: 'execute',\n    })\n\n    return result\n}\n\nasync function getIndexExe() {\n    let index\n    await executeAsModal(async () => {\n        index = await getIndexCommand()\n    })\n\n    return index\n}\nconst photoshop = require('photoshop')\n\nconst collapseFolderCommand = async (expand = false, recursive = false) => {\n    let result\n    try {\n        result = await batchPlay(\n            [\n                {\n                    _obj: 'set',\n                    _target: {\n                        _ref: [\n                            { _property: 'layerSectionExpanded' },\n                            {\n                                _ref: 'layer',\n                                _enum: 'ordinal',\n                                _value: 'targetEnum',\n                            },\n                        ],\n                    },\n                    to: expand,\n                    recursive,\n                    _options: { dialogOptions: 'dontDisplay' },\n                },\n            ],\n            { synchronousExecution: true }\n        )\n    } catch (e) {\n        console.error(e.message)\n    }\n    return result\n}\nasync function collapseFolderExe(layers, expand = false, recursive = false) {\n    for (let layer of layers) {\n        try {\n            await executeAsModal(async () => {\n                const is_visible = await layer.visible // don't change the visiblity of the layer when collapsing\n                await selectLayers([layer])\n                await collapseFolderCommand(expand, recursive)\n                layer.visible = is_visible\n            })\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\n\nclass Layer {\n    static doesLayerExist(layer) {\n        let b_exist = false\n        try {\n            if (typeof layer !== 'undefined' && layer && layer.name) {\n                //it will throw an error if the layer has been deleted\n                b_exist = true\n                // return true\n            }\n            // b_exist = true\n        } catch (e) {\n            b_exist = false\n            // console.warn(e)\n        }\n        return b_exist\n    }\n    static async getLayerInfo(layer) {\n        const bounds = layer.bounds\n        const height = bounds.bottom - bounds.top\n        const width = bounds.right - bounds.left\n        const layer_info = {\n            height: height,\n            width: width,\n            left: bounds.left,\n            right: bounds.right,\n            top: bounds.top,\n            bottom: bounds.bottom,\n        }\n        console.log('layer_info:', layer_info)\n        return layer_info\n    }\n    static async scaleTo(layer, new_width, new_height) {\n        await executeAsModal(async () => {\n            try {\n                const selection_info = await psapi.getSelectionInfoExe()\n                await psapi.unSelectMarqueeExe()\n\n                console.log('scaleLayer got called')\n                // const activeLayer = getActiveLayer()\n                // const activeLayer = await app.activeDocument.activeLayers[0]\n\n                const layer_info = await this.getLayerInfo(layer)\n                const scale_x_ratio = (new_width / layer_info.width) * 100\n                const scale_y_ratio = (new_height / layer_info.height) * 100\n                console.log('scale_x_y_ratio:', scale_x_ratio, scale_y_ratio)\n                // await layer.scale(\n                //     scale_x_ratio,\n                //     scale_y_ratio,\n                //     constants.ResampleMethod.BILINEAR\n                // )\n                await layer_util.Layer.resizeImageExe(\n                    scale_x_ratio,\n                    scale_y_ratio\n                )\n                await psapi.reSelectMarqueeExe(selection_info)\n            } catch (e) {\n                console.warn(e)\n            }\n        })\n    }\n    static async resizeImage(percent_width, percent_height) {\n        // let imageSizeDescriptor = {\n        //     _obj: 'imageSize',\n        //     scaleStyles: true,\n        //     constrainProportions: true,\n        //     interfaceIconFrameDimmed: {\n        //         _enum: 'interpolationType',\n        //         // _value: 'automaticInterpolation',\n        //         _value: 'bilinear',\n        //     },\n        //     _options: {\n        //         dialogOptions: 'dontDisplay',\n        //     },\n        // }\n\n        // if (width !== undefined && width !== null) {\n        //     imageSizeDescriptor.width = {\n        //         _unit: 'pixelsUnit',\n        //         _value: width,\n        //     }\n        // }\n        // if (height !== undefined && height !== null) {\n        //     imageSizeDescriptor.height = {\n        //         _unit: 'pixelsUnit',\n        //         _value: height,\n        //     }\n        // }\n        const setInterpolationMethodDesc = {\n            _obj: 'set',\n            _target: [\n                {\n                    _ref: 'property',\n                    _property: 'generalPreferences',\n                },\n                {\n                    _ref: 'application',\n                    _enum: 'ordinal',\n                    _value: 'targetEnum',\n                },\n            ],\n            to: {\n                _obj: 'generalPreferences',\n                interpolationMethod: {\n                    _enum: 'interpolationType',\n                    // _value: 'bilinear',\n                    _value: settings_tab_ts.store.data\n                        .scale_interpolation_method.photoshop,\n                },\n            },\n            _isCommand: true,\n        }\n        let imageSizeDescriptor = {\n            _obj: 'transform',\n            _target: [\n                {\n                    _ref: 'layer',\n                    _enum: 'ordinal',\n                    _value: 'targetEnum',\n                },\n            ],\n            freeTransformCenterState: {\n                _enum: 'quadCenterState',\n                _value: 'QCSAverage',\n            },\n            // offset: {\n            //     _obj: 'offset',\n            //     horizontal: {\n            //         _unit: 'pixelsUnit',\n            //         _value: 24.4388124547429,\n            //     },\n            //     vertical: {\n            //         _unit: 'pixelsUnit',\n            //         _value: -24.4388124547429,\n            //     },\n            // },\n            width: {\n                _unit: 'percentUnit',\n                _value: percent_width,\n            },\n            height: {\n                _unit: 'percentUnit',\n                _value: percent_height,\n            },\n            linked: true,\n            interfaceIconFrameDimmed: {\n                _enum: 'interpolationType',\n                // _value: 'bilinear',\n                _value: settings_tab_ts.store.data.scale_interpolation_method\n                    .photoshop,\n            },\n            _isCommand: true,\n        }\n\n        return batchPlay([setInterpolationMethodDesc, imageSizeDescriptor], {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        })\n    }\n    static async resizeImageExe(percent_width, percent_height) {\n        try {\n            await executeAsModal(async () => {\n                await this.resizeImage(percent_width, percent_height)\n            })\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    static async moveTo(layer, to_x, to_y) {\n        try {\n            await executeAsModal(async () => {\n                try {\n                    //translate doesn't work with selection active. so store the selection and then unselect. move the layer, then reselect the selection info\n                    const selection_info = await psapi.getSelectionInfoExe()\n                    await psapi.unSelectMarqueeExe()\n\n                    const layer_info = await this.getLayerInfo(layer)\n                    const top_dist = layer_info.top - to_y\n                    const left_dist = layer_info.left - to_x\n                    console.log('-left_dist, -top_dist', -left_dist, -top_dist)\n                    await layer.translate(-left_dist, -top_dist)\n\n                    await psapi.reSelectMarqueeExe(selection_info)\n                } catch (e) {\n                    console.warn(e)\n                }\n            })\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static resizeTo() {}\n    static fitSelection() {}\n    static async duplicateToDoc(layer, to_doc) {\n        const dupLayer = await layer.duplicate(to_doc)\n        // await selectLayers([dupLayer])\n        return dupLayer\n    }\n\n    static async duplicateLayerExe(layer) {\n        let layer_copy\n        try {\n            await executeAsModal(async () => {\n                layer_copy = await layer.duplicate()\n            })\n        } catch (e) {\n            console.warn('duplication error:', e)\n        }\n        return layer_copy\n    }\n\n    static {}\n}\n\nconst hasBackgroundLayerDesc = () => ({\n    _obj: 'get',\n    _target: [\n        { _property: 'hasBackgroundLayer' },\n        {\n            _ref: 'document',\n            _enum: 'ordinal',\n            _value: 'targetEnum',\n        },\n    ],\n})\nasync function hasBackgroundLayer() {\n    // check if a document has a background layer\n    try {\n        const result = await batchPlay([hasBackgroundLayerDesc()], {\n            synchronousExecution: true,\n            modalBehavior: 'execute',\n        })\n        const b_hasBackgroundLayer = result[0]?.hasBackgroundLayer\n        return b_hasBackgroundLayer\n    } catch (e) {\n        console.warn(e)\n    }\n}\nconst makeBackgroundLayerDesc = () => ({\n    _obj: 'make',\n    _target: [\n        {\n            _ref: 'backgroundLayer',\n        },\n    ],\n    using: {\n        _ref: 'layer',\n        _enum: 'ordinal',\n        _value: 'targetEnum',\n    },\n    _options: { failOnMissingProperty: false, failOnMissingElement: false },\n    // _options: {\n    //     dialogOptions: 'dontDisplay',\n    // },\n})\n\nconst createSolidLayerDesc = (r, g, b) => ({\n    _obj: 'make',\n    _target: [\n        {\n            _ref: 'contentLayer',\n        },\n    ],\n    using: {\n        _obj: 'contentLayer',\n        type: {\n            _obj: 'solidColorLayer',\n            color: {\n                _obj: 'RGBColor',\n                red: r,\n                grain: g,\n                blue: b,\n            },\n        },\n    },\n    _options: {\n        dialogOptions: 'dontDisplay',\n    },\n})\n\nasync function toggleActiveLayer() {\n    const result = await batchPlay(\n        [\n            {\n                _obj: 'show',\n                null: [\n                    {\n                        _ref: 'layer',\n                        _enum: 'ordinal',\n                        _value: 'targetEnum',\n                    },\n                ],\n                toggleOptionsPalette: true,\n                _options: {\n                    dialogOptions: 'dontDisplay',\n                },\n            },\n        ],\n        {}\n    )\n}\nconst toggleBackgroundLayerDesc = () => ({\n    _obj: 'show',\n    null: [\n        {\n            _ref: 'layer',\n            _property: 'background',\n        },\n    ],\n    toggleOptionsPalette: true,\n    _options: {\n        dialogOptions: 'dontDisplay',\n    },\n})\n\nasync function toggleBackgroundLayerExe() {\n    try {\n        await executeAsModal(async () => {\n            const result = await batchPlay([toggleBackgroundLayerDesc()], {\n                synchronousExecution: true,\n                modalBehavior: 'execute',\n            })\n            console.log('toggleBackgroundLayerExe result: ', result)\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function createBackgroundLayer(r = 255, g = 255, b = 255) {\n    try {\n        const has_background = await hasBackgroundLayer()\n        if (has_background) {\n            //no need to create a background layer\n            return null\n        }\n\n        //reselect the selection area if it exist\n\n        await executeAsModal(async () => {\n            //store the selection area and then unselected\n            const selectionInfo = await psapi.getSelectionInfoExe()\n            await psapi.unSelectMarqueeExe()\n            const active_layers = app.activeDocument.activeLayers\n\n            // await createNewLayerCommand('background') //create layer\n            //make the layer into background\n            const result = await batchPlay(\n                [createSolidLayerDesc(r, g, b), makeBackgroundLayerDesc()],\n                {\n                    synchronousExecution: true,\n                    modalBehavior: 'execute',\n                }\n            )\n\n            await psapi.reSelectMarqueeExe(selectionInfo)\n            await psapi.selectLayersExe(active_layers)\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function fixImageBackgroundLayer() {\n    //convert the background layer to a normal layer\n    //create a new layer\n    //convert the new layer to background\n}\nmodule.exports = {\n    createNewLayerExe,\n    deleteLayers,\n    getIndexExe,\n    collapseFolderExe,\n    Layer,\n    hasBackgroundLayer,\n    createBackgroundLayer,\n    createSolidLayerDesc,\n    makeBackgroundLayerDesc,\n    toggleBackgroundLayerExe,\n    toggleActiveLayer,\n}\n"
  },
  {
    "path": "utility/notification.js",
    "content": "const dialog_box = require('../dialog_box')\nconst psapi = require('../psapi')\nconst { createBackgroundLayer } = require('./layer')\nclass Notification {\n    static {}\n    static async webuiIsOffline() {\n        const r1 = await dialog_box.prompt(\n            'Automatic1111 is Offline',\n            'make sure Automatic1111 is running in the background',\n            ['Cancel', 'OK']\n        )\n\n        try {\n            if (r1 === 'Cancel') {\n                /* cancelled or No */\n                console.log('cancel')\n            } else if (r1 === 'OK') {\n                console.log('ok')\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async webuiAPIMissing() {\n        const r1 = await dialog_box.prompt(\n            \"The Plugin can't communicate with Automatic1111\",\n            'Automatic1111 is running, but you forgot to add --api flag to the webui command flags',\n            ['Cancel', 'OK']\n        )\n\n        try {\n            if (r1 === 'Cancel') {\n                /* cancelled or No */\n                console.log('cancel')\n            } else if (r1 === 'OK') {\n                console.log('ok')\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async backgroundLayerIsMissing() {\n        const r1 = await dialog_box.prompt(\n            'You need a white background layer present in your document',\n            '',\n            ['Cancel', 'Create']\n        )\n\n        try {\n            if (r1 === 'Cancel') {\n                /* cancelled or No */\n                console.log('cancel')\n                return false\n            } else if (r1 === 'Create') {\n                //store the selection area and then unselected\n                const selectionInfo = await psapi.getSelectionInfoExe()\n                await psapi.unSelectMarqueeExe()\n                const active_layers = app.activeDocument.activeLayers\n\n                //create a background layer with no selection active\n                await createBackgroundLayer()\n                console.log('create background layer')\n                //reselect the selection area if it exist\n\n                await psapi.reSelectMarqueeExe(selectionInfo)\n                await psapi.selectLayersExe(active_layers)\n                return true\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n        return false\n    }\n    static async inactiveSelectionArea(\n        is_active_session,\n        button_label = 'Continue Session'\n    ) {\n        let buttons = ['Cancel', 'Rectangular Marquee']\n        if (is_active_session) {\n            buttons.push(button_label)\n        }\n        const r1 = await dialog_box.prompt(\n            'Please Select a Rectangular Area',\n            'You Forgot to select a Rectangular Area',\n            buttons\n        )\n        if (r1 === 'Cancel') {\n            /* cancelled or No */\n            console.log('cancel')\n            return false\n        } else if (r1 === 'Rectangular Marquee') {\n            console.log('Rectangular Marquee')\n            psapi.selectMarqueeRectangularToolExe()\n            return false // should this be false?! what does true and false means in this context?! Yes: it should be false since boolean value represent wither we have an active selection area or not\n        } else if (r1 === button_label) {\n            await selection_ts.activateSessionSelectionArea()\n            return true\n        }\n        return false\n    }\n}\n\nmodule.exports = {\n    Notification,\n}\n"
  },
  {
    "path": "utility/online_data.json",
    "content": "{\n    \"new_version\": \"v1.4.1\",\n    \"update_message\": \"Your version is outdated.Please visit our Github page and download the one click installer / .ccx file.\\nRun the .ccx file and it will automatically update the current version of your plug in. No data will be lost.\"\n}\n"
  },
  {
    "path": "utility/presets/controlnet_preset.js",
    "content": "const MaintainPositionSettings = {\n    0: {\n        module: 'openpose',\n        model: 'control_sd15_openpose [fef5e48e]',\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 0.3,\n        guessmode: null,\n    },\n    1: {\n        module: 'depth',\n        model: 'control_sd15_depth [fef5e48e]',\n        weight: 0.8,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 0.6,\n        guessmode: null,\n    },\n}\n\nconst Pose_Depth_Canny_HandFix = {\n    0: {\n        module: 'openpose',\n        model: 'control_sd15_openpose [fef5e48e]',\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 1,\n        guessmode: null,\n    },\n    1: {\n        module: 'depth',\n        model: 'control_sd15_depth [fef5e48e]',\n        weight: 1.3,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0.3,\n        guidance_end: 1,\n        guessmode: null,\n    },\n    2: {\n        module: 'canny',\n        model: 'control_sd15_canny [fef5e48e]',\n        weight: 1.3,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0.3,\n        guidance_end: 1,\n        guessmode: null,\n    },\n}\n\nMaintainComposition_Character = {\n    0: {\n        module: 'openpose',\n        model: 'control_sd15_openpose [fef5e48e]',\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 0.5,\n        guessmode: null,\n    },\n    1: {\n        module: 'canny',\n        model: 'control_sd15_canny [fef5e48e]',\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 0.8,\n        guessmode: null,\n    },\n    2: {\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 1,\n        guessmode: null,\n    },\n}\n\nconst LogoCreation = {\n    0: {\n        module: 'canny',\n        model: 'control_sd15_canny [fef5e48e]',\n        weight: 1.3,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 0.9,\n        guessmode: null,\n    },\n    1: {\n        module: 'scribble',\n        model: 'control_sd15_scribble [fef5e48e]',\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 1,\n        guessmode: null,\n    },\n    2: {\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 1,\n        guessmode: null,\n    },\n}\n\nconst Backgrounds = {\n    0: {\n        module: 'mlsd',\n        model: 'control_sd15_mlsd [fef5e48e]',\n        weight: 1.3,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 0.7,\n        guessmode: null,\n    },\n    1: {\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 1,\n        guessmode: null,\n    },\n    2: {\n        weight: 1,\n        resize_mode: null,\n        lowvram: null,\n        processor_res: null,\n        threshold_a: null,\n        threshold_b: null,\n        guidance_start: 0,\n        guidance_end: 1,\n        guessmode: null,\n    },\n}\nconst ControlNetNativePresets = {\n    'Maintain Position': MaintainPositionSettings,\n    'Hand Fix': Pose_Depth_Canny_HandFix,\n    'Maintain Composition (Character)': MaintainComposition_Character,\n    'Logo Creation': LogoCreation,\n    Backgrounds: Backgrounds,\n}\nmodule.exports = {\n    ControlNetNativePresets,\n}\n"
  },
  {
    "path": "utility/sampler.js",
    "content": "samplers = [\n    {\n        name: 'Euler a',\n        aliases: ['k_euler_a', 'k_euler_ancestral'],\n        options: {},\n    },\n    {\n        name: 'Euler',\n        aliases: ['k_euler'],\n        options: {},\n    },\n    {\n        name: 'LMS',\n        aliases: ['k_lms'],\n        options: {},\n    },\n    {\n        name: 'Heun',\n        aliases: ['k_heun'],\n        options: {},\n    },\n    {\n        name: 'DPM2',\n        aliases: ['k_dpm_2'],\n        options: {\n            discard_next_to_last_sigma: 'True',\n        },\n    },\n    {\n        name: 'DPM2 a',\n        aliases: ['k_dpm_2_a'],\n        options: {\n            discard_next_to_last_sigma: 'True',\n        },\n    },\n    {\n        name: 'DPM++ 2S a',\n        aliases: ['k_dpmpp_2s_a'],\n        options: {},\n    },\n    {\n        name: 'DPM++ 2M',\n        aliases: ['k_dpmpp_2m'],\n        options: {},\n    },\n    {\n        name: 'DPM++ SDE',\n        aliases: ['k_dpmpp_sde'],\n        options: {},\n    },\n    {\n        name: 'DPM fast',\n        aliases: ['k_dpm_fast'],\n        options: {},\n    },\n    {\n        name: 'DPM adaptive',\n        aliases: ['k_dpm_ad'],\n        options: {},\n    },\n    {\n        name: 'LMS Karras',\n        aliases: ['k_lms_ka'],\n        options: {\n            scheduler: 'karras',\n        },\n    },\n    {\n        name: 'DPM2 Karras',\n        aliases: ['k_dpm_2_ka'],\n        options: {\n            scheduler: 'karras',\n            discard_next_to_last_sigma: 'True',\n        },\n    },\n    {\n        name: 'DPM2 a Karras',\n        aliases: ['k_dpm_2_a_ka'],\n        options: {\n            scheduler: 'karras',\n            discard_next_to_last_sigma: 'True',\n        },\n    },\n    {\n        name: 'DPM++ 2S a Karras',\n        aliases: ['k_dpmpp_2s_a_ka'],\n        options: {\n            scheduler: 'karras',\n        },\n    },\n    {\n        name: 'DPM++ 2M Karras',\n        aliases: ['k_dpmpp_2m_ka'],\n        options: {\n            scheduler: 'karras',\n        },\n    },\n    {\n        name: 'DPM++ SDE Karras',\n        aliases: ['k_dpmpp_sde_ka'],\n        options: {\n            scheduler: 'karras',\n        },\n    },\n    {\n        name: 'DDIM',\n        aliases: [],\n        options: {},\n    },\n    {\n        name: 'PLMS',\n        aliases: [],\n        options: {},\n    },\n]\n\nmodule.exports = { samplers }\n"
  },
  {
    "path": "utility/sd_scripts/horde.js",
    "content": "async function requestModelsHorde() {\n    //get the models list from url\n    // https://stablehorde.net/api/v2/status/models\n\n    console.log('requestModelsHorde: ')\n\n    const full_url = 'https://stablehorde.net/api/v2/status/models'\n    let request = await fetch(full_url)\n    let json = await request.json()\n    console.log('hordes models json:')\n    console.dir(json)\n\n    return json\n}\n\nfunction addHordeModelMenuItem(model_title, model_name) {\n    // console.log(model_title,model_name)\n    const menu_item_element = document.createElement('sp-menu-item')\n    menu_item_element.className = 'mModelMenuItemHorde'\n    menu_item_element.innerHTML = model_title\n\n    menu_item_element.dataset.name = model_name\n    return menu_item_element\n}\n\nasync function refreshModelsHorde() {\n    try {\n        let g_models_horde = await requestModelsHorde()\n        // const models_menu_element = document.getElementById('mModelsMenu')\n        // models_menu_element.value = \"\"\n        //(optional): sort the models\n\n        g_models_horde.sort(function (a, b) {\n            return b.count - a.count\n        })\n        // g_models_horde = g_models_horde.sort( compareModelCounts );\n        document.getElementById('mModelsMenuHorde').innerHTML = ''\n        let model_item_random = addHordeModelMenuItem('Random', 'Random')\n        // model_item_random.selected = true\n        document\n            .getElementById('mModelsMenuHorde')\n            .appendChild(model_item_random)\n        for (let model of g_models_horde) {\n            // console.log(model.name, model.count) //Log\n            const model_html_tile = `${model.name}: ${model.count}`\n            const model_item_element = addHordeModelMenuItem(\n                model_html_tile,\n                model.name\n            )\n            if (model.name === 'stable_diffusion') {\n                // TODO: refactor this code outside the for loop\n                // maybe call it in an init function\n                //selection the stable diffusion model by default\n                model_item_element.selected = true\n            }\n            document\n                .getElementById('mModelsMenuHorde')\n                .appendChild(model_item_element)\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction getModelHorde() {\n    return [...document.getElementsByClassName('mModelMenuItemHorde')].filter(\n        (e) => e.selected == true\n    )[0].dataset.name\n}\n\nfunction getScriptArgs() {\n    const model = getModelHorde()\n    const b_nsfw = document.getElementById('chUseNSFW').checked\n    const b_shared_laion = document.getElementById('chUseSharedLaion').checked\n\n    let seed_variation = document.getElementById('slSeedVariation').value\n    seed_variation = parseInt(seed_variation)\n    const script_args_json = {\n        model: model,\n        nsfw: b_nsfw,\n        shared_laion: b_shared_laion,\n        seed_variation: seed_variation,\n        post_processing_1: 'None',\n        post_processing_2: 'None',\n        post_processing_3: 'None',\n    }\n    const script_args = Object.values(script_args_json)\n    return script_args\n}\n\ndocument\n    .getElementById('btnRefreshModelsHorde')\n    .addEventListener('click', async () => {\n        await refreshModelsHorde()\n    })\n\nconst script_name = 'Run on Stable Horde'\n\nrefreshModelsHorde() //refresh the model when importing the script\n\nmodule.exports = {\n    requestModelsHorde,\n    refreshModelsHorde,\n    getModelHorde,\n\n    getScriptArgs,\n    script_name,\n}\n"
  },
  {
    "path": "utility/sdapi/config.js",
    "content": "class SdConfig {\n    constructor() {\n        this.config //store sd options\n    }\n\n    async getConfig() {\n        try {\n            this.config = await sdapi.requestGetConfig()\n            return this.config\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    getUpscalerModels() {\n        try {\n            // const upscaler_comp = this.config.components.filter(comp =>comp.props.elem_id === \"txt2img_hr_upscaler\")[0]\n            let upscaler_comp\n            // console.log('this.config: ', this.config)\n            for (let comp of this.config.components) {\n                if (comp?.props?.elem_id) {\n                    const elem_id = comp?.props?.elem_id\n                    if (elem_id === 'txt2img_hr_upscaler') {\n                        console.log('elem_id: ', elem_id)\n                        upscaler_comp = comp\n                        break\n                    }\n                }\n            }\n            console.log('upscaler_comp: ', upscaler_comp)\n            const upscalers = upscaler_comp.props.choices\n\n            return upscalers\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    getControlNetMaxModelsNum() {\n        try {\n            let max_models_num = 0\n            for (let comp of this.config.components) {\n                if (comp?.props?.elem_id) {\n                    const elem_id = comp?.props?.elem_id\n                    if (elem_id === 'setting_control_net_max_models_num') {\n                        console.log(\n                            'setting_control_net_max_models_num: ',\n                            comp?.props?.value\n                        )\n                        max_models_num = comp?.props?.value\n                        break\n                    }\n                }\n            }\n            console.log('max_models_num: ', max_models_num)\n            return max_models_num\n        } catch (e) {\n            console.warn(e)\n            return 1 // default max number is one\n        }\n    }\n\n    getControlNetPreprocessors() {\n        try {\n            let max_models_num\n            let choices\n            for (let comp of this.config.components) {\n                const label = comp?.props?.label\n                if (label === 'Preprocessor') {\n                    choices = comp?.props?.choices\n                    break\n                }\n            }\n            console.log('Preprocessor list: ', choices)\n            return choices\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\n\nmodule.exports = {\n    SdConfig,\n}\n"
  },
  {
    "path": "utility/sdapi/horde_native.js",
    "content": "const general = require('../general')\nconst psapi = require('../../psapi')\nconst html_manip = require('../html_manip')\nconst layer_util = require('../layer')\nconst dummy = require('../dummy')\nconst io = require('../io')\nclass HordeSettings {\n    static {}\n    static async saveSettings() {\n        try {\n            const settings = await getSettings()\n\n            let native_horde_settings = await mapPluginSettingsToHorde(settings)\n            const horde_api_key = html_manip.getHordeApiKey()\n            native_horde_settings['api_key'] = html_manip.getHordeApiKey()\n            await io.IOJson.saveHordeSettingsToFile(native_horde_settings)\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    static async loadSettings() {\n        try {\n            let native_horde_settings =\n                await io.IOJson.loadHordeSettingsFromFile()\n            html_manip.setHordeApiKey(native_horde_settings['api_key'])\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n}\nclass hordeGenerator {\n    //horde generation process:\n    //*) get the settings\n    //*) get send request\n    //*) wait for response\n    //*) load the image to the canvas\n    //*) move and scale image to the selection\n    //*) save the image to history/data folder\n    //*) load the image data into the plugin / viewer tab\n    //*)\n\n    //other options:\n    //*)interrupt the generation process\n    //*)cancel the generation process on error\n\n    constructor() {\n        this.horde_settings\n        this.plugin_settings\n        this.currentGenerationResult = null\n        this.requestStatus = null\n        this.isProcessHordeResultCalled = false\n        this.maxWaitTime = 0\n        this.waiting = 0\n        this.isCanceled = false\n        this.horde_id = null\n        this.last_horde_id = null\n    }\n\n    async getSettings() {\n        try {\n            const workers = await getWorkers()\n\n            const workers_ids = getWorkerID(workers)\n            const settings = await getSettings()\n            this.plugin_settings = settings\n            let payload = await mapPluginSettingsToHorde(settings)\n            // payload['workers'] = workers_ids\n            payload['workers'] = []\n\n            this.horde_settings = payload\n            return this.horde_settings\n        } catch (e) {\n            console.warn('getSettings: ', e)\n        }\n    }\n\n    /**\n     * @returns {json}{payload, dir_name, images_info, metadata}\n     */\n    async generateRequest(settings) {\n        try {\n            this.horde_id = null //reset request_id\n            this.requestStatus = await requestHorde(settings)\n            if (this.requestStatus?.message) {\n                await app.showAlert(this.requestStatus?.message)\n            }\n            this.horde_id = this.requestStatus.id\n            console.log(\n                'generateRequest this.requestStatus: ',\n                this.requestStatus\n            )\n\n            const images_info = await this.startCheckingProgress()\n            const result = await this.toGenerationFormat(images_info)\n            console.warn('generateRequest() images_info: ', images_info)\n            console.warn('generateRequest() result: ', result)\n\n            html_manip.updateProgressBarsHtml(0) // reset progress bar\n            return result\n        } catch (e) {\n            this.horde_id = null\n            console.warn(e)\n        }\n    }\n    async generate() {\n        //*) get the settings\n        this.horde_settings = await this.getSettings()\n        //*) send generateRequest() and trigger the progress bar update\n        this.isCanceled = false\n        const result = await this.generateRequest(this.horde_settings)\n\n        return result\n        //*) store the generation result in the currentGenerationResult\n\n        //*) return the generation currentGenerationResult\n    }\n\n    isValidGeneration() {\n        if (this.currentGenerationResult) {\n            return true // if true if valid, false otherwise\n        } else {\n            return false\n        }\n    }\n    preGenerate() {}\n    // async layerToBase64WebpToFile\n    //convert layer to .webp file\n    //read the .webp file as buffer data base64 .webp\n    async layerToBase64Webp(layer, document_name, image_name) {\n        const width = html_manip.getWidth()\n        const height = html_manip.getHeight()\n        const image_buffer = await psapi.newExportPng(\n            layer,\n            image_name,\n            width,\n            height\n        )\n\n        const base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64\n        //send the base64 to the server to save the file in the desired directory\n        // await sdapi.requestSavePng(base64_image, image_name)\n        await io.saveFileInSubFolder(base64_image, document_name, image_name)\n        return base64_image\n    }\n\n    async layerToBase64ToFile(layer, document_name, image_name) {\n        const width = html_manip.getWidth()\n        const height = html_manip.getHeight()\n        const image_buffer = await psapi.newExportPng(\n            layer,\n            image_name,\n            width,\n            height\n        )\n\n        const base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64\n        //send the base64 to the server to save the file in the desired directory\n        // await sdapi.requestSavePng(base64_image, image_name)\n        await io.saveFileInSubFolder(base64_image, document_name, image_name)\n        return base64_image\n    }\n\n    async toGenerationFormat(images_info) {\n        //convert the output of native horde generation to the values that generate() can use\n        try {\n            //images_info[0] = {path:path,base64:base64png}\n            // let last_images_paths = await silentImagesToLayersExe(images_info)\n            let last_images_paths = {}\n            for (const image_info of images_info) {\n                const path = image_info['path']\n                // const base64_image = image_info['base64']\n                const layer = image_info['layer']\n                const [document_name, image_name] = path.split('/')\n\n                // await saveFileInSubFolder(base64_image, document_name, image_name)\n                image_info['base64'] = await this.layerToBase64ToFile(\n                    layer,\n                    document_name,\n                    image_name\n                )\n\n                // delete the layer made by the webp image.\n                await layer_util.deleteLayers([layer])\n                // await layer.delete()\n\n                // const json_file_name = `${image_name.split('.')[0]}.json`\n                this.plugin_settings['auto_metadata'] =\n                    image_info?.auto_metadata\n\n                // g_generation_session.base64OutputImages[path] =\n                //     image_info['base64']\n                // await saveJsonFileInSubFolder(\n                //     this.plugin_settings,\n                //     document_name,\n                //     json_file_name\n                // ) //save the settings\n                // last_images_paths[path] = image_info['layer']\n                // images_info.push({\n                //     base64: i,\n                //     path: image_path,\n                //     auto_metadata: auto_metadata_json,\n                // })\n                // // console.log(\"metadata_json: \", metadata_json)\n            }\n\n            // if (g_generation_session.isFirstGeneration) {\n            //     //store them in the generation session for viewer manager to use\n            //     g_generation_session.image_paths_to_layers = last_images_paths\n            // } else {\n            //     g_generation_session.image_paths_to_layers = {\n            //         ...g_generation_session.image_paths_to_layers,\n            //         ...last_images_paths,\n            //     }\n            //     // g_number_generation_per_session++\n\n            // }\n            const dir_name = 'temp_dir_name'\n            return {\n                // payload: payload,\n                dir_name: dir_name,\n                images_info: images_info,\n                metadata: this.plugin_settings,\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    async toSession(images_info) {\n        try {\n            //images_info[0] = {path:path,base64:base64png}\n            // let last_images_paths = await silentImagesToLayersExe(images_info)\n            let last_images_paths = {}\n            for (const image_info of images_info) {\n                const path = image_info['path']\n                // const base64_image = image_info['base64']\n                const layer = image_info['layer']\n                const [document_name, image_name] = path.split('/')\n\n                // await saveFileInSubFolder(base64_image, document_name, image_name)\n                image_info['base64'] = await this.layerToBase64ToFile(\n                    layer,\n                    document_name,\n                    image_name\n                )\n                const json_file_name = `${image_name.split('.')[0]}.json`\n                this.plugin_settings['auto_metadata'] =\n                    image_info?.auto_metadata\n\n                g_generation_session.base64OutputImages[path] =\n                    image_info['base64']\n                await io.saveJsonFileInSubFolder(\n                    this.plugin_settings,\n                    document_name,\n                    json_file_name\n                ) //save the settings\n                last_images_paths[path] = image_info['layer']\n            }\n\n            if (g_generation_session.isFirstGeneration) {\n                //store them in the generation session for viewer manager to use\n                g_generation_session.image_paths_to_layers = last_images_paths\n            } else {\n                g_generation_session.image_paths_to_layers = {\n                    ...g_generation_session.image_paths_to_layers,\n                    ...last_images_paths,\n                }\n                // g_number_generation_per_session++\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    async interruptRequest(horde_id) {\n        try {\n            console.log('interruptRquest():')\n\n            const full_url = `https://stablehorde.net/api/v2/generate/status/${horde_id}`\n\n            console.log(full_url)\n\n            let response = await fetch(full_url, {\n                method: 'DELETE',\n                headers: {\n                    Accept: 'application/json',\n                    'Content-Type': 'application/json',\n                    // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',\n                    'Client-Agent': 'unknown:0:unknown',\n                },\n            })\n\n            let result = await response.json()\n            console.log('interruptReqquest result:', result)\n\n            return result\n        } catch (e) {\n            console.warn(e)\n            return\n        }\n    }\n    async interrupt() {\n        try {\n            html_manip.updateProgressBarsHtml(0)\n            // g_generation_session.request_status = Enum.requestStatus['']\n            this.last_horde_id = this.horde_id\n            this.horde_id = null //horde_id could be used startCheckingprogress() so we need to nullify it as soon as possible. TODO: refactor this dependency.\n            this.isCanceled = true\n            // this.interval_id = clearTimeout(this.interval_id)\n            await this.interruptRequest(this.last_horde_id)\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n\n    async processHordeResult() {\n        //*) get the result from the horde server\n        //*) save them locally to output directory\n        //*) import them into the canvas\n        //*) resize and move the layers to fit the selection\n        //*) return the results to be stored and processed by the g_generation_session\n        try {\n            if (this.isProcessHordeResultCalled) {\n                return\n            }\n            this.isProcessHordeResultCalled = true\n            console.log('horde request is done')\n            // g_b_request_result = true\n            const temp_id = this.horde_id //this.horde_id will reset\n            // cancelRequestClientSide()\n            g_horde_generation_result = await requestHordeStatus(temp_id)\n\n            const generations = g_horde_generation_result.generations\n            const writeable_entry = await getCurrentDocFolder()\n            const images_info = [] //{path:image_path,base64:}\n            for (const image_horde_container of generations) {\n                try {\n                    const url = image_horde_container.img\n                    const image_file_name = general.newOutputImageName('webp')\n\n                    const image_layer = await downloadItExe(\n                        url,\n                        writeable_entry,\n                        image_file_name\n                    ) //download the image from url, it works even with .webp format\n                    const image_png_file_name =\n                        general.convertImageNameToPng(image_file_name)\n\n                    const uuid = await getUniqueDocumentId()\n                    const image_path = `${uuid}/${image_png_file_name}` //this is the png path\n                    images_info.push({\n                        path: image_path,\n                        base64: dummy.getDummyBase64(), //TODO:change this to the base64_png\n                        layer: image_layer,\n                    })\n                    await psapi.layerToSelection(\n                        g_generation_session.selectionInfo\n                    ) //TODO: create a safe layerToSelection function\n                } catch (e) {\n                    console.warn(e)\n                }\n            }\n            this.isProcessHordeResultCalled = false //reset for next generation\n            return images_info\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    updateHordeProgressBar(check_horde_status) {\n        //update the progress bar proceduer\n        console.log('this.maxWaitTime: ', this.maxWaitTime)\n        console.log(\n            \"check_horde_status['wait_time']: \",\n            check_horde_status['wait_time']\n        )\n        console.log(\n            \"check_horde_status['waiting']: \",\n            check_horde_status['waiting']\n        )\n\n        this.maxWaitTime = Math.max(\n            check_horde_status['wait_time'],\n            this.maxWaitTime\n        ) // return the max time value, so we could use to calculate the complection percentage\n        const delta_time = this.maxWaitTime - check_horde_status['wait_time']\n\n        if (isNaN(this.maxWaitTime) || parseInt(this.maxWaitTime) === 0) {\n            this.maxWaitTime = 0 // reset to zero\n        } else {\n            console.log('delta_time:', delta_time)\n            console.log('this.maxWaitTime:', this.maxWaitTime)\n\n            const completion_percentage = (delta_time / this.maxWaitTime) * 100\n            console.log('completion_percentage:', completion_percentage)\n\n            html_manip.updateProgressBarsHtml(completion_percentage)\n        }\n    }\n    async startCheckingProgress() {\n        console.log('startCheckingProgress is called')\n        return await new Promise((resolve, reject) => {\n            if (this.horde_id && !this.isCanceled) {\n                this.interval_id = setTimeout(async () => {\n                    try {\n                        console.warn(\n                            'startCheckingProgress(): horde_id and isCanceled',\n                            this.horde_id,\n                            this.isCanceled\n                        )\n                        //check the request status\n                        const check_json = await requestHordeCheck(\n                            this.horde_id\n                        )\n\n                        this.updateHordeProgressBar(check_json)\n\n                        if (check_json['done']) {\n                            // this.interval_id = clearTimeout(this.interval_id)\n\n                            const images_info = await this.processHordeResult()\n                            if (this.horde_id) {\n                                this.last_horde_id = this.horde_id\n                                this.horde_id = null\n                            }\n                            return resolve(images_info)\n                        } else {\n                            //the request is not done and the user hasn't canceled it\n                            console.warn(\n                                'startCheckingProgress(): reqursive startCheckingProgress call',\n                                this.horde_id,\n                                this.isCanceled\n                            )\n                            const horde_result =\n                                await this.startCheckingProgress() // start another check\n                            return resolve(horde_result) // return the result of the new check\n                        }\n                    } catch (e) {\n                        console.warn(e)\n                        const result = await this.startCheckingProgress()\n                        return resolve(result)\n                    }\n                }, 3000)\n            } else {\n                console.warn(\n                    'startCheckingProgress: else block',\n                    this.horde_id,\n                    this.isCanceled\n                )\n                return resolve()\n            }\n        })\n    }\n}\nconst webui_to_horde_samplers = {\n    'Euler a': 'k_euler_a',\n    Euler: 'k_euler',\n    LMS: 'k_lms',\n    Heun: 'k_heun',\n    DPM2: 'k_dpm_2',\n    'DPM2 a': 'k_dpm_2_a',\n    'DPM++ 2S a': 'k_dpmpp_2s_a',\n    'DPM++ 2M': 'k_dpmpp_2m',\n    'DPM++ SDE': 'k_dpmpp_sde',\n    'DPM fast': 'k_dpm_fast',\n    'DPM adaptive': 'k_dpm_adaptive',\n    'LMS Karras': 'k_lms',\n    'DPM2 Karras': 'k_dpm_2',\n    'DPM2 a Karras': 'k_dpm_2_a',\n    'DPM++ 2S a Karras': 'k_dpmpp_2s_a',\n    'DPM++ 2M Karras': 'k_dpmpp_2m',\n    'DPM++ SDE Karras': 'k_dpmpp_sde',\n    DDIM: 'ddim',\n    PLMS: 'plms',\n}\n\n//get workers\n//select a worker\n//send a request => requestHorde(horde_settings)\n//check for progress => requestHordeCheck(request_id)\n//when progress is full, request the result => requestHordeStatus(request_id)\n\nasync function mapPluginSettingsToHorde(plugin_settings) {\n    const { getModelHorde } = require('../sd_scripts/horde')\n    const ps = plugin_settings // for shortness\n    const sampler = webui_to_horde_samplers[ps['sampler_index']]\n    const model = getModelHorde()\n    let horde_prompt\n    if (ps['negative_prompt'].length > 0) {\n        horde_prompt = `${ps['prompt']} ### ${ps['negative_prompt']}`\n    } else {\n        horde_prompt = ps['prompt'] //no negative prompt\n    }\n    const extra_payload = {}\n    if (ps['mode'] === 'img2img') {\n        // payload['source_image'] = ps['init_images']\n        // let current_doc_entry =await getCurrentDocFolder()\n        // let webp_file = await current_doc_entry.getEntry('temp.webp')\n        // let base64_webp =    await io.IO.base64WebpFromFile(webp_file)\n        // payload['source_image'] = io.IO.base64WebpFromFile()\n        // console.log('base64_webp:', base64_webp)\n\n        // const dummy_str = getDummyWebpBase64()\n        // if (base64_webp === dummy_str) {\n        //     console.warn('the same base64')\n        // } else {\n        //     console.warn('different base64')\n        // }\n        // payload['source_image'] = dummy_str\n\n        // payload['source_image'] = base64.b64encode(buffer.getvalue()).decode() //does it need to be webp?\n\n        const init_image_base64_webp = await io.IO.base64PngToBase64Webp(\n            ps['init_images'][0]\n        )\n        extra_payload['source_image'] = init_image_base64_webp\n        extra_payload['source_processing'] = 'img2img'\n    } else if (ps['mode'] === 'inpaint' || ps['mode'] === 'outpaint') {\n        const init_image_base64_webp = await io.IO.base64PngToBase64Webp(\n            ps['init_images'][0]\n        )\n        const mask_base64_webp = await io.IO.base64PngToBase64Webp(ps['mask'])\n        extra_payload['source_processing'] = 'inpainting'\n        extra_payload['source_image'] = init_image_base64_webp\n        extra_payload['source_mask'] = mask_base64_webp\n        // payload[\"source_mask\"] = base64.b64encode(buffer.getvalue()).decode()//does it need to be webp?\n    }\n\n    let seed = ps['seed']\n    if (parseInt(ps['seed']) === -1) {\n        const random_seed = Math.floor(Math.random() * 100000000000 + 1) // Date.now() doesn't have enough resolution to avoid duplicate\n        seed = random_seed.toString()\n    }\n    const width = general.nearestMultiple(ps['width'], 64)\n    const height = general.nearestMultiple(ps['height'], 64)\n    const nsfw = html_manip.getUseNsfw()\n    let horde_payload = {\n        prompt: horde_prompt,\n        params: {\n            sampler_name: sampler,\n            toggles: [1, 4],\n            cfg_scale: ps['cfg_scale'],\n            denoising_strength: ps['denoising_strength'],\n            seed: seed,\n            height: height,\n            width: width,\n            seed_variation: 1,\n            post_processing: ['GFPGAN'],\n            karras: false,\n            tiling: false,\n            steps: parseInt(ps['steps']),\n            n: 1,\n        },\n        nsfw: nsfw,\n        trusted_workers: true,\n        censor_nsfw: false,\n        // workers: ['4c79ab19-8e6c-4054-83b3-773b7ce71ece'],\n        // workers: workers_ids,\n        // models: ['stable_diffusion'],\n        models: [model],\n        // source_image: 'string',\n        // source_processing: 'img2img',\n        // source_mask: 'string',\n        ...extra_payload,\n        r2: true,\n        shared: false,\n    }\n    return horde_payload\n}\n\nfunction getWorkerID(workers_json) {\n    let workers_ids = []\n    for (worker of workers_json) {\n        workers_ids.push(worker?.id)\n    }\n    console.log('workers_ids:', workers_ids)\n\n    return workers_ids\n}\nasync function getWorkers() {\n    const full_url = 'https://stablehorde.net/api/v2/workers'\n    // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n    console.log(full_url)\n\n    let request = await fetch(full_url, {\n        method: 'GET',\n        headers: {\n            Accept: 'application/json',\n        },\n    })\n\n    let workers = await request.json()\n    // const workers_ids = getWorkerID(workers)\n    console.log('requestHorde workers:', workers)\n    return workers\n}\nasync function requestHorde(payload) {\n    // const workers = await getWorkers()\n\n    // const workers_ids = getWorkerID(workers)\n    // const settings = await getSettings()\n    // payload = mapPluginSettingsToHorde(settings)\n    // payload['workers'] = workers_ids\n    // payload = {\n    //     prompt: 'string',\n    //     params: {\n    //         sampler_name: 'k_lms',\n    //         toggles: [1, 4],\n    //         cfg_scale: 5,\n    //         denoising_strength: 0.75,\n    //         // seed: 'string',\n    //         height: 512,\n    //         width: 512,\n    //         seed_variation: 1,\n    //         post_processing: ['GFPGAN'],\n    //         karras: false,\n    //         tiling: false,\n    //         steps: 5,\n    //         n: 1,\n    //     },\n    //     nsfw: false,\n    //     trusted_workers: true,\n    //     censor_nsfw: false,\n    //     // workers: ['4c79ab19-8e6c-4054-83b3-773b7ce71ece'],\n    //     workers: workers_ids,\n    //     models: ['stable_diffusion'],\n    //     // source_image: 'string',\n    //     // source_processing: 'img2img',\n    //     // source_mask: 'string',\n    //     r2: true,\n    //     shared: false,\n    // }\n    try {\n        console.log('requestHorde():')\n\n        const full_url = 'https://stablehorde.net/api/v2/generate/async'\n        // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n        console.log(full_url)\n\n        const horde_api_key = html_manip.getHordeApiKey()\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n                apikey: horde_api_key,\n\n                'Client-Agent': 'unknown:0:unknown',\n            },\n            body: JSON.stringify(payload),\n        })\n\n        let json = await request.json()\n        console.log('requestHorde json:', json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\nasync function requestHordeCheck(id) {\n    try {\n        console.log('requestHordeCheck():')\n        const base_url = 'https://stablehorde.net/api/v2/generate/check'\n\n        const full_url = `${base_url}/${id}`\n        // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n        console.log(full_url)\n        const payload = {}\n        let request = await fetch(full_url, {\n            method: 'GET',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n                // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',\n                'Client-Agent': 'unknown:0:unknown',\n            },\n        })\n\n        let json = await request.json()\n        console.log('requestHordeCheck json:', json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\n\nasync function requestHordeStatus(id) {\n    try {\n        console.log('requestHordeStatus():')\n        const base_url = 'https://stablehorde.net/api/v2/generate/status'\n\n        const full_url = `${base_url}/${id}`\n        // const full_url = 'https://stablehorde.net/api/v2/generate/sync'\n        console.log(full_url)\n        const payload = {}\n        let request = await fetch(full_url, {\n            method: 'GET',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n                // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',\n                'Client-Agent': 'unknown:0:unknown',\n            },\n        })\n\n        let json = await request.json()\n        console.log('requestHordeStatus json:', json)\n\n        return json\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nlet g_horde_generation_result\nlet g_b_request_result = false\nfunction cancelRequestClientSide() {\n    this.interval_id = clearTimeout(this.interval_id)\n    // g_id = null\n    g_b_request_result = false\n}\n\nmodule.exports = {\n    hordeGenerator,\n    HordeSettings,\n}\n"
  },
  {
    "path": "utility/sdapi/options.js",
    "content": "class SdOptions {\n    constructor() {\n        // this.status = false // true if we have a valid copy of sd options, false otherwise\n        this.options //store sd options\n    }\n\n    async getOptions() {\n        try {\n            // if (this.status) {\n            //   return this.options\n            // } else {\n            //   this.options = await sdapi.requestGetOptions()\n            //   if (this.options) {\n            //     this.status = true\n            //   }\n            // }\n            this.options = await sdapi.requestGetOptions()\n            return this.options\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    getCurrentModel() {\n        const current_model = this.options?.sd_model_checkpoint\n        return current_model\n    }\n    getInpaintingMaskWeight() {\n        const inpainting_mask_weight = this.options?.inpainting_mask_weight\n        return inpainting_mask_weight\n    }\n}\n// const sd_options = new SdOptions()\n// sd_options.option?.sd_model_checkpoint\n\nmodule.exports = {\n    SdOptions,\n}\n"
  },
  {
    "path": "utility/sdapi/prompt_shortcut.js",
    "content": "function find_words_inside_braces(string) {\n    const re = /\\{(.*?)\\}/g\n    let keywords = string.match(re)\n    // console.log('keywords: ', keywords)\n    if (!keywords) {\n        //avoid null keywords\n        keywords = []\n    }\n    return keywords\n}\n\nfunction replaceShortcut(text, prompt_shortcut_json) {\n    const original_keywords = find_words_inside_braces(text)\n    const strip_keywords = original_keywords.map((s) => {\n        let content = s.slice(1, -1) //remove '{' and  '}'\n        content = content.trim() //remove any space in the beginning  and end of content\n        return content\n    })\n\n    let i = 0\n    for (const word of strip_keywords) {\n        if (word.length > 0 && prompt_shortcut_json.hasOwnProperty(word)) {\n            const prompt = prompt_shortcut_json[word]\n            // console.log('prompt: ', prompt)\n            text = text.replace(original_keywords[i], prompt)\n        }\n    }\n    // console.log('final text: ', text)\n    return text\n}\nmodule.exports = {\n    find_words_inside_braces,\n    replaceShortcut,\n}\n"
  },
  {
    "path": "utility/sdapi/python_replacement.js",
    "content": "//how to get environment variable in javascript\nconst settings_tab = require('../tab/settings')\nconst { getPromptShortcut } = require('../html_manip')\nconst general = require('../general')\n// function newOutputImageName(format = 'png') {\n//     const random_id = Math.floor(Math.random() * 100000000000 + 1) // Date.now() doesn't have enough resolution to avoid duplicate\n//     const image_name = `output- ${Date.now()}-${random_id}.${format}`\n//     console.log('generated image name:', image_name)\n//     return image_name\n// }\n\nfunction convertMetadataToJson(metadata_str) {\n    try {\n        // console.log('metadata_str:', metadata_str)\n        const last_new_line_index = metadata_str.lastIndexOf('\\n')\n\n        const prompt = metadata_str.slice(0, last_new_line_index)\n        const other_settings = metadata_str.slice(last_new_line_index + 1, -1)\n\n        // console.log('prompt:', prompt)\n        // console.log('other_settings:', other_settings)\n        const sub_settings = other_settings.split(',')\n        // console.log('sub_settings: ', sub_settings)\n\n        const settings_json = {}\n        ;[settings_json['prompt'], settings_json['negative_prompt']] =\n            prompt.split('Negative prompt: ')\n\n        for (const setting of sub_settings) {\n            let [key, value] = setting.split(':').map((s) => s.trimLeft())\n            // key =  key.lstrip(' ')\n            // value =  value.lstrip(' ')\n            settings_json[key] = value\n            // import json\n            // settings_json = json.dumps(settings_dict)\n            // print(\"settings_dict: \",settings_dict)\n            // print(\"settings_json \",settings_json)\n        }\n\n        return settings_json\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function getAuto1111Metadata(base64_image) {\n    try {\n        console.log('getAuto1111Metadata: ')\n\n        const full_url = `${g_sd_url}/sdapi/v1/png-info`\n\n        const payload = {\n            image: 'data:image/png;base64,' + base64_image,\n        }\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n        })\n\n        let json = await request.json()\n        // console.log(\"json['info']:\", json['info'])\n\n        // console.log('getAuto1111Metadata json:', json)\n\n        return json['info']\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function convertToStandardResponse(settings, images, uuid) {\n    try {\n        //standardized the response between modes and backends\n        const uniqueDocumentId = uuid // maybe use the generation_session uuid\n\n        const image_paths = []\n\n        const metadata = []\n        const images_info = []\n\n        for (i of images) {\n            let auto_metadata_json = {}\n            try {\n                const auto_metadata_str = await getAuto1111Metadata(i)\n                auto_metadata_json = convertMetadataToJson(auto_metadata_str)\n                // console.warn(\n                //     'auto_metadata_json.Seed:',\n                //     auto_metadata_json?.Seed\n                // )\n            } catch (e) {\n                console.warn(e)\n                auto_metadata_json = {} // set the metadata to empty if there an error while getting the metadata\n            }\n\n            const image_name = general.newOutputImageName()\n            const image_path = `${uniqueDocumentId}/${image_name}`\n\n            images_info.push({\n                base64: i,\n                path: image_path,\n                auto_metadata: auto_metadata_json,\n            })\n            // console.log(\"metadata_json: \", metadata_json)\n        }\n        const dir_name = 'temp_dir_name'\n        return {\n            payload: settings,\n            dir_name: dir_name,\n            images_info: images_info,\n            metadata: metadata,\n        }\n    } catch (e) {\n        console.warn(e)\n    }\n}\nfunction replacePromptsWithShortcuts(\n    prompt,\n    negative_prompt,\n    prompt_shortcut_dic\n) {\n    //     const prompt_shortcut_dict = prompt_shortcut.load()\n    //     prompt_shortcut_dict.update(payload[\"prompt_shortcut_ui_dict\"])\n    new_prompt = prompt_shortcut.replaceShortcut(prompt, prompt_shortcut_dic)\n    // # edit negative prompt, replaceShortcut(negative_prompt)\n    new_negative_prompt = prompt_shortcut.replaceShortcut(\n        negative_prompt,\n        prompt_shortcut_dic\n    )\n    return [new_prompt, new_negative_prompt]\n}\nasync function txt2ImgRequest(payload) {\n    console.log('payload:', payload)\n\n    if (payload['use_prompt_shortcut']) {\n        const [new_prompt, new_negative_prompt] = replacePromptsWithShortcuts(\n            payload['prompt'],\n            payload['negative_prompt'],\n            payload['prompt_shortcut_ui_dict']\n        )\n        payload['prompt'] = new_prompt\n        payload['negative_prompt'] = new_negative_prompt\n    }\n\n    const endpoint = 'sdapi/v1/txt2img'\n    try {\n        console.log('txt2ImgRequest(): about to send a fetch request')\n\n        const full_url = `${g_sd_url}/${endpoint}`\n        console.log(full_url)\n\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n        })\n\n        let r = await request.json()\n        // console.log('txt2ImgRequest json:', r)\n\n        const uniqueDocumentId = payload['uniqueDocumentId']\n\n        const image_paths = []\n\n        const metadata = []\n        const images_info = []\n\n        for (i of r['images']) {\n            let auto_metadata_json = {}\n            try {\n                const auto_metadata_str = await getAuto1111Metadata(i)\n                auto_metadata_json = convertMetadataToJson(auto_metadata_str)\n            } catch (e) {\n                console.warn(e)\n                auto_metadata_json = {} // set the metadata to empty if there an error while getting the metadata\n            }\n\n            const image_name = general.newOutputImageName()\n            const image_path = `${uniqueDocumentId}/${image_name}`\n\n            images_info.push({\n                base64: i,\n                path: image_path,\n                auto_metadata: auto_metadata_json,\n            })\n        }\n        const dir_name = 'temp_dir_name'\n        return {\n            payload: payload,\n            dir_name: dir_name,\n            images_info: images_info,\n            metadata: metadata,\n        }\n    } catch (e) {\n        console.warn(e)\n        return {}\n    }\n}\nfunction getExtensionUrl() {\n    const extension_type = settings_tab_ts.store.data.extension_type\n    let extension_url\n\n    if (extension_type === 'auto1111_extension') {\n        extension_url = `${g_sd_url}/sdapi/auto-photoshop-sd`\n    } else if (extension_type === 'proxy_server') {\n        extension_url = 'http://127.0.0.1:8000'\n    } else {\n        //none\n        extension_url = ''\n    }\n    return extension_url\n}\n\nasync function openUrlRequest(url) {\n    try {\n        const payload = {\n            url: url,\n        }\n\n        const extension_url = getExtensionUrl()\n        const full_url = `${extension_url}/open/url/`\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n            // \"body\": payload\n        })\n\n        let r = await request.json()\n\n        console.log('openUrlRequest json:', r)\n        return r['url']\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function maskExpansionRequest(original_mask, mask_expansion_value, blur) {\n    // const endpoint = 'sdapi/v1/img2img'\n    // const full_url = `${g_sd_url}/${endpoint}`\n\n    try {\n        const payload = {\n            mask: original_mask,\n            mask_expansion: mask_expansion_value,\n            blur: blur,\n        }\n\n        const extension_url = getExtensionUrl()\n        const full_url = `${extension_url}/mask/expansion/`\n        let request = await fetch(full_url, {\n            method: 'POST',\n            headers: {\n                Accept: 'application/json',\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(payload),\n            // \"body\": payload\n        })\n\n        let r = await request.json()\n\n        // console.log('maskExpansionRequest json:', r)\n        return r['mask']\n    } catch (e) {\n        console.warn(e)\n    }\n}\nasync function img2ImgRequest(sd_url, payload) {\n    console.log('payload:', payload)\n\n    if (payload['use_prompt_shortcut']) {\n        const [new_prompt, new_negative_prompt] = replacePromptsWithShortcuts(\n            payload['prompt'],\n            payload['negative_prompt'],\n            payload['prompt_shortcut_ui_dict']\n        )\n        payload['prompt'] = new_prompt\n        payload['negative_prompt'] = new_negative_prompt\n    }\n\n    const endpoint = 'sdapi/v1/img2img'\n\n    const full_url = `${sd_url}/${endpoint}`\n    let request = await fetch(full_url, {\n        method: 'POST',\n        headers: {\n            Accept: 'application/json',\n            'Content-Type': 'application/json',\n        },\n        body: JSON.stringify(payload),\n        // \"body\": payload\n    })\n\n    let r = await request.json()\n\n    console.log('img2ImgRequest json:', r)\n\n    const uniqueDocumentId = payload['uniqueDocumentId']\n    // dir_fullpath,dirName = serverHelper.getUniqueDocumentDirPathName(uniqueDocumentId)\n    // serverHelper.createFolder(dir_fullpath)\n    const image_paths = []\n    const metadata = []\n    const images_info = []\n\n    for (i of r['images']) {\n        // image = Image.open(io.BytesIO(base64.b64decode(i.split(\",\",1)[0])))\n        let auto_metadata_json = {}\n        try {\n            const auto_metadata_str = await getAuto1111Metadata(i)\n            auto_metadata_json = convertMetadataToJson(auto_metadata_str)\n        } catch (e) {\n            console.warn(e)\n            auto_metadata_json = {} // set the metadata to empty if there an error while getting the metadata\n        }\n        // response2 = await client.post(url=f'{sd_url}/sdapi/v1/png-info', json=png_payload, timeout=None)\n        // pnginfo = PngImagePlugin.PngInfo()\n        // pnginfo.add_text(\"parameters\", response2.json().get(\"info\"))\n        // image_name = f'output- {time.time()}.png'\n        // image_path = f'output/{dirName}/{image_name}'\n        // image_paths.append(image_path)\n        // image.save(f'./{image_path}', pnginfo=pnginfo)\n\n        // metadata_info = response2.json().get(\"info\")\n        // metadata_json = metadata_to_json.convertMetadataToJson(metadata_info)\n        // metadata.append(metadata_json)\n        const image_name = general.newOutputImageName()\n        const image_path = `${uniqueDocumentId}/${image_name}`\n\n        images_info.push({\n            base64: i,\n            path: image_path,\n            auto_metadata: auto_metadata_json,\n        })\n        // print(\"metadata_json: \", metadata_json)\n    }\n    const dir_name = 'temp_dir_name'\n    // return [dirName, images_info, metadata]\n    return {\n        payload: payload,\n        dir_name: dir_name,\n        images_info: images_info,\n        metadata: metadata,\n    }\n}\n\nasync function savePromptShortcut(json, file_name) {\n    console.warn(\n        \"savePromptShortcut() is deprecated, use it's IO class instead \"\n    )\n    try {\n        const json_file_name = file_name\n\n        const folder = await storage.localFileSystem.getDataFolder()\n\n        const file = await folder.createFile(json_file_name, {\n            type: storage.types.file,\n            overwrite: true,\n        })\n\n        const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)\n        await file.write(JSONInPrettyFormat, {\n            format: storage.formats.utf8,\n            append: false,\n        })\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nasync function loadPromptShortcut(file_name) {\n    const json_file_name = file_name\n\n    const folder = await storage.localFileSystem.getDataFolder()\n\n    try {\n        const json_entry = await folder.getEntry(json_file_name)\n        if (json_entry) {\n            // await json_entry.read()\n\n            const json = JSON.parse(\n                await json_entry.read({\n                    format: storage.formats.utf8,\n                })\n            )\n            return json\n        }\n    } catch (e) {\n        const file = await folder.createFile('prompt_shortcut.json', {type: storage.types.file, overwrite: true});\n        if (file.isFile) {\n            await file.write('{}', {append: false});\n            data = {};\n            return data\n        }\n        console.warn(e)\n        return {}\n    }\n}\n\nasync function extraSingleImageRequest(sd_url, payload) {\n    console.log('extraSingleImageRequest payload:', payload)\n\n    const endpoint = 'sdapi/v1/extra-single-image'\n\n    const full_url = `${sd_url}/${endpoint}`\n    let request = await fetch(full_url, {\n        method: 'POST',\n        headers: {\n            Accept: 'application/json',\n            'Content-Type': 'application/json',\n        },\n        body: JSON.stringify(payload),\n        // \"body\": payload\n    })\n\n    let r = await request.json()\n\n    const images_info = []\n\n    const image = r['image']\n\n    let auto_metadata_json = {}\n\n    const uniqueDocumentId = payload['uniqueDocumentId']\n    const image_name = general.newOutputImageName()\n    const image_path = `${uniqueDocumentId}/${image_name}`\n\n    images_info.push({\n        base64: image,\n        path: image_path,\n        auto_metadata: auto_metadata_json,\n    })\n\n    console.log('extraSingleImageRequest response json:', r)\n\n    const dir_name = 'temp_dir_name'\n    const metadata = []\n\n    return {\n        payload: payload,\n        dir_name: dir_name,\n        images_info: images_info,\n        metadata: metadata,\n    }\n}\n\nmodule.exports = {\n    txt2ImgRequest,\n    img2ImgRequest,\n    maskExpansionRequest,\n    getExtensionUrl,\n    savePromptShortcut,\n    loadPromptShortcut,\n\n    convertMetadataToJson,\n    openUrlRequest,\n    replacePromptsWithShortcuts,\n    extraSingleImageRequest,\n    convertToStandardResponse,\n}\n"
  },
  {
    "path": "utility/session.js",
    "content": "const { cleanLayers } = require('../psapi')\nconst psapi = require('../psapi')\nconst io = require('./io')\nconst Enum = require('../enum')\n\nconst { base64ToBase64Url } = require('./general')\nconst html_manip = require('./html_manip')\nconst layer_util = require('./layer')\n\nconst SessionState = {\n    Active: 'active',\n    Inactive: 'inactive',\n}\nconst GarbageCollectionState = {\n    Accept: 'accept', // accept all generated images\n    Discard: 'discard', //discard all generated images\n    DiscardSelected: 'discard_selected',\n    AcceptSelected: 'accept_selected', //accept_selected only chosen images\n}\n\nclass GenerationSession {\n    constructor() {\n        //this should be unique session id and it also should act as the total number of sessions been created in the project\n        this.id = 0\n        this.state = SessionState['Inactive']\n        this.mode = 'txt2img'\n        this.selectionInfo = null\n        this.isFirstGeneration = true // only before the first generation is requested should this be true\n        this.outputGroup\n        this.prevOutputGroup\n        this.isLoadingActive = false\n        this.base64OutputImages = {} //image_id/path => base64_image\n        this.base64initImages = {} //init_image_path => base64\n        this.base64maskImage = []\n        this.base64maskExpansionImage\n        this.activeBase64InitImage\n        this.activeBase64MaskImage\n        this.image_paths_to_layers = {}\n        this.progress_layer\n        this.last_settings //the last settings been used for generation\n        this.controlNetImage = [] // base64 images (one for each control net)\n        this.controlNetMask = [] // base64 images (one for each control net)\n        this.request_status = Enum.RequestStateEnum['Finished'] //finish or ideal state\n        this.is_control_net = false\n        this.control_net_selection_info\n        this.control_net_preview_selection_info\n    }\n    isActive() {\n        return this.state === SessionState['Active']\n    }\n    isInactive() {\n        return this.state === SessionState['Inactive']\n    }\n    activate() {\n        this.state = SessionState['Active']\n    }\n    deactivate() {\n        this.state = SessionState['Inactive']\n    }\n    name() {\n        return `session - ${this.id}`\n    }\n\n    deleteInitImageLayers() {}\n    async closePreviousOutputGroup() {\n        try {\n            //close the previous output folder\n\n            if (this.prevOutputGroup) {\n                // const is_visible = await this.prevOutputGroup.visible\n                await layer_util.collapseFolderExe(\n                    [this.prevOutputGroup],\n                    false\n                ) // close the folder group\n                // and reselect the current output folder for clarity\n                await psapi.selectLayersExe([this.outputGroup])\n                // this.prevOutputGroup.visible = is_visible\n            }\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    isSameMode(selected_mode) {\n        if (this.mode === selected_mode) {\n            return true\n        }\n        return false\n    }\n    loadLastSession() {\n        //load the last session from the server\n    }\n    saveCurrentSession() {\n        //all session info will be saved in a json file in the project folder\n    }\n    async moveToTopOfOutputGroup(layer) {\n        const output_group_id = await this.outputGroup.id\n        let group_index = await psapi.getLayerIndex(output_group_id)\n        const indexOffset = 1 //1 for background, 0 if no background exist\n        await executeAsModal(async () => {\n            await psapi.selectLayersExe([layer]) //the move command is selection selection sensitive\n            await psapi.moveToGroupCommand(group_index - indexOffset, layer.id)\n        })\n    }\n\n    async deleteProgressLayer() {\n        try {\n            await layer_util.deleteLayers([this.progress_layer]) // delete the old progress layer\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    deleteProgressImageHtml() {\n        try {\n            // await layer_util.deleteLayers([this.progress_layer]) // delete the old progress layer\n            // document.getElementById('progressImage').style.width = '0px'\n            // document.getElementById('progressImage').style.height = '0px'\n\n            document.getElementById(\n                'divProgressImageViewerContainer'\n            ).style.height = '0px'\n        } catch (e) {\n            console.warn(e)\n        }\n    }\n    async deleteProgressImage() {\n        preview.store.updateProperty('image', null)\n        this.deleteProgressImageHtml()\n        await this.deleteProgressLayer()\n    }\n    async setControlNetImageHelper() {\n        const width = html_manip.getWidth()\n        const height = html_manip.getHeight()\n\n        //get the selection from the canvas as base64 png, make sure to resize to the width and height slider\n        const selectionInfo = await psapi.getSelectionInfoExe()\n        this.control_net_selection_info = selectionInfo\n        this.control_net_preview_selection_info = selectionInfo\n        // const base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(\n        //     selectionInfo,\n        //     true,\n        //     width,\n        //     height\n        // )\n\n        const use_silent_mode = html_manip.getUseSilentMode()\n        let layer = null\n        if (!use_silent_mode) {\n            await psapi.snapshot_layerExe()\n            const snapshotLayer = await app.activeDocument.activeLayers[0]\n            layer = snapshotLayer\n        }\n        const base64_image =\n            await io.IO.getSelectionFromCanvasAsBase64Interface(\n                width,\n                height,\n                layer,\n                selectionInfo,\n                true,\n                use_silent_mode\n            )\n\n        await layer_util.deleteLayers([layer]) //delete the snapshot layer if it exists\n        return base64_image\n    }\n    async setControlNetImage(control_net_index = 0, base64_image) {\n        //check if the selection area is active\n        //convert layer to base64\n        //the width and height of the exported image\n        // const base64_image = this.setControlNetImageHelper()\n        this.controlNetImage[control_net_index] = base64_image\n        html_manip.setControlImageSrc(\n            base64ToBase64Url(base64_image),\n            control_net_index\n        )\n        // console.log('base64_img:', base64_image)\n        // await io.IO.base64ToLayer(base64_image)\n    }\n}\n\n//REFACTOR: move to generation_settings.js\nasync function getSettings(session_data) {\n    let payload = {}\n\n    try {\n        const extension_type = settings_tab_ts.store.data.extension_type // get the extension type\n        payload['selection_info'] = session_data?.selectionInfo\n        const numberOfBatchSize = parseInt(sd_tab_store.data.batch_size)\n\n        const prompt = multiPrompts.getPrompt().positive\n        const negative_prompt = multiPrompts.getPrompt().negative\n        const hi_res_fix = sd_tab_store.data.enable_hr\n\n        const upscaler = sd_tab_store.data.hr_upscaler\n        const cfg_scale = sd_tab_store.data.cfg\n\n        function calculateSeed(init_seed, batch_index, batch_size) {\n            if (init_seed === -1) return -1\n            // const seed = init_seed + batch_index * batch_size\n            const seed = init_seed + BigInt(batch_index) * BigInt(batch_size)\n            return seed\n        }\n\n        // const init_seed = parseInt(sd_tab_store.data.seed)\n        const init_seed = BigInt(sd_tab_store.data.seed)\n\n        const seed = calculateSeed(\n            init_seed,\n            g_current_batch_index,\n            numberOfBatchSize\n        )\n\n        const use_sharp_mask = settings_tab_ts.store.data.extension_type\n        const mask_blur = settings_tab_ts.store.data.use_sharp_mask\n            ? 0\n            : sd_tab_store.data.mask_blur\n        const mask_expansion = sd_tab_store.data.mask_expansion\n\n        const inpaint_full_res_padding =\n            sd_tab_store.data.inpaint_full_res_padding\n\n        // console.dir(numberOfImages)\n        const bUsePromptShortcut =\n            settings_tab_ts.store.data.use_prompt_shortcut\n        let prompt_shortcut_ui_dict = {}\n        try {\n            let prompt_shortcut_string =\n                document.getElementById('taPromptShortcut').value\n            prompt_shortcut_ui_dict = JSON.parse(prompt_shortcut_string)\n        } catch (e) {\n            console.warn(\n                `warning prompt_shortcut_ui_dict is not valid Json obj: ${e}`\n            )\n            prompt_shortcut_ui_dict = {}\n        }\n\n        // const slider_width = document.getElementById(\"slWidth\").value\n        // gWidth = getWidthFromSlider(slider_width)\n        const original_width = sd_tab_store.data.width\n        const original_height = sd_tab_store.data.height\n\n        const width = general.nearestMultiple(original_width, 8)\n        const height = general.nearestMultiple(original_height, 8)\n\n        //const hScale = html_manip.getSliderSdValue_Old('hrScale',1)\n\n        const uniqueDocumentId = await getUniqueDocumentId()\n        const h_denoising_strength = sd_tab_store.data.hr_denoising_strength\n\n        //Note: store the sampler names in json file if auto is offline or auto api is unmounted\n\n        const sampler_name = sd_tab_store.data.sampler_name\n\n        const mode = session_data?.rb_mode || sd_tab_store.data.rb_mode // Use the 'rb_mode' from the session, if not available, fallback to the 'rb_mode' from the interface.\n\n        const b_restore_faces = sd_tab_store.data.restore_faces\n\n        let denoising_strength = h_denoising_strength\n        if (mode == 'inpaint' || mode == 'outpaint') {\n            payload['inpaint_full_res'] = sd_tab_store.data.inpaint_full_res\n\n            payload['inpaint_full_res_padding'] = inpaint_full_res_padding\n\n            payload['inpainting_fill'] = sd_tab_store.data.inpainting_fill\n            payload['mask_expansion'] = mask_expansion\n\n            payload['mask'] = session_data?.mask\n            payload['expanded_mask'] = session_data?.mask\n            if (\n                use_sharp_mask === false &&\n                payload['mask'] &&\n                mask_expansion > 0\n            ) {\n                //only if mask is available and sharp_mask is off\n                // use blurry and expanded mask\n\n                const expanded_mask = await py_re.maskExpansionRequest(\n                    payload['mask'],\n                    payload['mask_expansion'],\n                    mask_blur\n                )\n                if (expanded_mask) {\n                    payload['expanded_mask'] = expanded_mask\n                    payload['mask'] = expanded_mask\n                    session_store.data.expanded_mask = expanded_mask\n                }\n            }\n            // viewer.store.mask = payload['mask'] // make sure\n        }\n\n        if (mode == 'img2img' || mode == 'inpaint' || mode == 'outpaint') {\n            denoising_strength = sd_tab_store.data.denoising_strength\n            payload['denoising_strength'] = denoising_strength\n\n            payload['init_images'] = [session_data?.init_image]\n\n            if (settings_tab_ts.store.data.use_image_cfg_scale_slider) {\n                payload['image_cfg_scale'] = sd_tab_store.data.image_cfg_scale // we may need to check if model is pix2pix\n            }\n\n            if (\n                scripts.script_store.isInstalled() &&\n                scripts.script_store.is_active &&\n                scripts.script_store.selected_script_name !== 'None' &&\n                scripts.script_store.is_selected_script_available\n            ) {\n                payload['script_args'] = scripts.script_store.orderedValues()\n\n                payload['script_name'] =\n                    scripts.script_store.selected_script_name //'Ultimate SD upscale'\n            }\n        }\n\n        function setAlwaysOnScripts() {\n            const data = after_detailer_script.store.toJsFunc().data\n            // console.log('setAlwaysOnScripts=> data:', data)\n            let ad_controlnet_module = 'None'\n            if (data.controlnet_model?.includes('inpaint')) {\n                ad_controlnet_module = 'inpaint_global_harmonious'\n            }\n            const alwayson_scripts = {\n                ADetailer: {\n                    args: [\n                        data.is_enabled,\n                        {\n                            ad_model: data.ad_model,\n                            ad_prompt: data.prompt,\n                            ad_negative_prompt: data.negativePrompt,\n                            ad_confidence: data.ad_conf,\n                            ad_mask_min_ratio: 0.0,\n                            ad_mask_max_ratio: 1.0,\n                            ad_dilate_erode: 32,\n                            ad_x_offset: 0,\n                            ad_y_offset: 0,\n                            ad_mask_merge_invert: 'None',\n                            ad_mask_blur: 4,\n                            ad_denoising_strength: 0.4,\n                            ad_inpaint_only_masked: true,\n                            ad_inpaint_only_masked_padding: 0,\n                            ad_use_inpaint_width_height: false,\n                            ad_inpaint_width: 512,\n                            ad_inpaint_height: 512,\n                            ad_use_steps: true,\n                            ad_steps: 28,\n                            ad_use_cfg_scale: false,\n                            ad_cfg_scale: 7.0,\n                            ad_use_sampler: false,\n                            ad_sampler: sampler_name, //use the current sd sampler\n                            ad_use_noise_multiplier: false,\n                            ad_noise_multiplier: 1.0,\n                            ad_restore_face: false,\n\n                            ad_controlnet_model: data.controlnet_model,\n                            // ad_controlnet_module: data.controlnet_module,\n                            ad_controlnet_module: ad_controlnet_module,\n                            ad_controlnet_weight: data.controlNetWeight,\n                            ad_controlnet_guidance_start: 0.0,\n                            ad_controlnet_guidance_end: 1.0,\n                        },\n                    ],\n                },\n            }\n            if (!data?.is_installed) {\n                delete alwayson_scripts['ADetailer']\n            }\n            return alwayson_scripts\n        }\n\n        const alwyason_scripts = setAlwaysOnScripts()\n        payload['alwayson_scripts'] = {\n            ...(payload['alwayson_scripts'] || {}),\n            ...alwyason_scripts,\n        }\n\n        if (hi_res_fix && width >= 512 && height >= 512) {\n            payload['enable_hr'] = hi_res_fix\n            payload['hr_scale'] = sd_tab_store.data.hr_scale // Scale\n            payload['hr_upscaler'] = upscaler // Upscaler\n            payload['hr_second_pass_steps'] =\n                sd_tab_store.data.hr_second_pass_steps\n        }\n\n        const backend_type = html_manip.getBackendType()\n        if (backend_type === backendTypeEnum['Auto1111HordeExtension']) {\n            payload['script_name'] = script_horde.script_name\n            payload['script_args'] = script_horde.getScriptArgs()\n        } else if (\n            payload['script_name'] === script_horde.script_name &&\n            backend_type !== backendTypeEnum['Auto1111HordeExtension']\n        ) {\n            delete payload['script_name']\n            delete payload['script_args']\n        }\n\n        if (bUsePromptShortcut) {\n            //replace the prompt with the prompt shortcut equivalent\n            const [new_prompt, new_negative_prompt] =\n                py_re.replacePromptsWithShortcuts(\n                    prompt,\n                    negative_prompt,\n                    prompt_shortcut_ui_dict\n                )\n\n            //used in generation\n            payload['prompt'] = new_prompt\n            payload['negative_prompt'] = new_negative_prompt\n\n            //used to when resote settings from metadata\n            payload['original_prompt'] = prompt\n            payload['original_negative_prompt'] = negative_prompt\n        } else {\n            //use the same prompt as in the prompt textarea\n            payload['prompt'] = prompt\n            payload['negative_prompt'] = negative_prompt\n\n            payload['original_prompt'] = prompt\n            payload['original_negative_prompt'] = negative_prompt\n        }\n\n        payload['clip_skip'] =\n            settings_tab_ts.store.data.CLIP_stop_at_last_layers\n        payload = {\n            ...payload,\n            // prompt: prompt,\n            // negative_prompt: negative_prompt,\n            steps: sd_tab_store.data.steps,\n            // n_iter: numberOfImages,\n            sampler_index: sampler_name,\n            width: width,\n            height: height,\n            denoising_strength: denoising_strength,\n            batch_size: numberOfBatchSize,\n            cfg_scale: cfg_scale,\n            seed: seed.toString(),\n            mask_blur: 4, //mask_blur, // don't use auto1111 blur, instead use Auto-Photoshop-SD blur\n            use_sharp_mask: use_sharp_mask,\n            use_prompt_shortcut: bUsePromptShortcut,\n            prompt_shortcut_ui_dict: prompt_shortcut_ui_dict,\n            uniqueDocumentId: uniqueDocumentId,\n            mode: mode,\n            restore_faces: b_restore_faces,\n            tiling: sd_tab_store.data.tiling,\n            // script_args: script_args,\n            // script_name:\"Run on Stable Horde\"\n        }\n    } catch (e) {\n        console.error(e)\n    }\n    return payload\n}\n\nmodule.exports = {\n    GenerationSession,\n    GarbageCollectionState,\n    SessionState,\n    getSettings,\n}\n"
  },
  {
    "path": "utility/tab/image_search_tab.js",
    "content": "const sdapi = require('../../sdapi_py_re')\nconst { image_search } = require('../../typescripts/dist/bundle')\n\nconst storage = require('uxp').storage\nconst fs = storage.localFileSystem\n\n//REFACTOR: move to events.js\ndocument\n    .getElementById('btnImageSearch')\n    .addEventListener('click', async function () {\n        try {\n            const keywords = document.getElementById('imageSearchField').value\n            const image_search_objs = await sdapi.imageSearch(keywords)\n\n            const thumbnails = image_search_objs.map((obj) => obj.thumbnail)\n            const src_list = image_search_objs.map((obj) => obj.image)\n            image_search.store.updateProperty('thumbnails', thumbnails)\n            image_search.store.updateProperty('images', src_list)\n        } catch (e) {\n            console.warn(`imageSearch warning: ${e}`)\n        }\n    })\n"
  },
  {
    "path": "utility/tab/settings.js",
    "content": "const io = require('../io')\n\nfunction setUseSharpMask() {\n    console.warn('setUseSharpMask is not setup')\n}\n\ndocument.getElementById('btnGetDocPath').addEventListener('click', async () => {\n    const docPath = await io.IOFolder.getDocumentFolderNativePath()\n    document.getElementById('tiDocPath').value = docPath\n\n    const uuid = await getUniqueDocumentId()\n    doc_entry = await io.IOFolder.getDocFolder(uuid)\n    await shell.openPath(doc_entry.nativePath)\n})\n\ndocument.getElementById('btnSdUrl').addEventListener('click', async () => {\n    //change the sdUrl in server in proxy server\n    // console.log('you clicked btnSdUrl')\n    let new_sd_url = document.getElementById('tiSdUrl').value\n    changeSdUrl(new_sd_url)\n})\n\nfunction getSdUrlHtml() {\n    let sd_url = document.getElementById('tiSdUrl').value\n    return sd_url\n}\nfunction setSdUrlHtml(sd_url) {\n    document.getElementById('tiSdUrl').value = sd_url\n}\nasync function changeSdUrl(sd_url) {\n    sd_url = sd_url.trim()\n    console.log('sd_url.trim(): ', sd_url)\n\n    if (sd_url.length > 0) {\n        //check if the last character of the url has \"/\" or '\\' and remove it\n\n        last_index = sd_url.length - 1\n\n        if (sd_url[last_index] === '/' || sd_url[last_index] === '\\\\') {\n            sd_url = sd_url.slice(0, -1)\n        }\n\n        //submit the change\n        await sdapi.changeSdUrl(sd_url)\n    }\n}\n\nasync function saveSettings() {\n    const settings_tab_settings = {\n        use_sharp_mask: settings_tab_ts.store.data.use_sharp_mask,\n        extension_type: settings_tab_ts.store.data.extension_type,\n        sd_url: getSdUrlHtml(),\n    }\n\n    const folder = await io.IOFolder.getSettingsFolder()\n    await io.IOJson.saveJsonToFile(\n        settings_tab_settings,\n        folder,\n        'settings_tab.json'\n    )\n}\nasync function loadSettings() {\n    try {\n        const folder = await io.IOFolder.getSettingsFolder()\n        let settings_tab_settings = await io.IOJson.loadJsonFromFile(\n            folder,\n            'settings_tab.json'\n        )\n        setSdUrlHtml(settings_tab_settings['sd_url'])\n        await changeSdUrl(settings_tab_settings['sd_url'])\n    } catch (e) {\n        console.warn(e)\n    }\n}\n\nfunction getUseOriginalPrompt() {\n    const b_use_original_prompt = document.getElementById(\n        'chUseOriginalPrompt'\n    ).checked\n    return b_use_original_prompt\n}\n\ndocument\n    .getElementById('btnSaveSettingsTabs')\n    .addEventListener('click', async () => {\n        await saveSettings()\n    })\n\nmodule.exports = {\n    setUseSharpMask,\n\n    getSdUrlHtml,\n    setSdUrlHtml,\n    changeSdUrl,\n    loadSettings,\n    saveSettings,\n\n    getUseOriginalPrompt,\n}\n"
  },
  {
    "path": "utility/tips.js",
    "content": "//tips that will display when you hover over a html element\nconst tips_json = {\n    snapshot: '',\n    txt2img: 'use this mode to generate images from text only',\n    img2img: 'use this mode to generate variation of an image',\n    inpaint:\n        'use this mode to generate variation of a small area of an image, while keeping the rest of the image intact',\n    outpaint:\n        'use this mode to (1) fill any missing area of an image,(2) expand an image',\n    generate: 'create',\n    discardAll: 'Delete all generated images from the canvas',\n    acceptAll: 'Keep all generated images on the canvas',\n    acceptSelected: 'Keep only the highlighted images',\n    discardSelected: 'Delete only the highlighted images',\n    modelMenu: 'select a model',\n    refresh: 'Refresh the plugin, only fixes minor issues.',\n    prompt_shortcut: 'use {keyword} form the prompts library',\n    inpaint: 'use when you need to modify an already existing part of an image',\n    img2img: 'use this mode when you want to generate variation of an image',\n    txt2img: 'use this mode to generate images based on text only',\n    batchNumber:\n        'the number of images to generate at once.The larger the number more VRAM stable diffusion will use.',\n    steps: 'how long should stable diffusion take to generate an image',\n    selection_mode_ratio:\n        'will auto fill the width and height slider to the same ratio as the selection area',\n    selection_mode_precise:\n        'auto fill width and height slider to the size as the selection area',\n    selection_mode_ignore:\n        'you will have to fill the width and height slider manually',\n    cfg_scale: 'larger value will put more emphasis on the prompt',\n    preset_menu:\n        'auto fill the plugin with smart settings, to speed up your working process.',\n    width: 'the generated image width',\n    height: 'the generated image height',\n    mask_expansion:\n        \"the larger the value the more the mask will expand, '0' means use precise masking, use in combination with the mask blur\",\n    mask_content_fill: '',\n}\n\nmodule.exports = { tips_json }\n"
  }
]