Files
disty 5acb9afa8e add hidden flows
add Ctrl+Alt+Enter
2025-01-04 20:03:34 +02:00

468 lines
16 KiB
JavaScript

import StateManager from './js/common/scripts/stateManager.js';
import MultiComponent from './js/common/components/MultiComponent.js';
import InputComponent from "./js/common/components/InputComponent.js";
import ToggleComponent from "./js/common/components/ToggleComponent.js";
import DataComponent from "./js/common/components/DataComponent.js";
import Seeder from "./js/common/components/Seeder.js";
import Stepper from "./js/common/components/Stepper.js";
import MultiStepper from "./js/common/components/MultiStepper.js";
import DropdownStepper from "./js/common/components/DropdownStepper.js";
import DimensionSelector from './js/common/components/DimSelector.js';
import Dropdown from './js/common/components/Dropdown.js';
import imageLoaderComp from './js/common/components/imageLoaderComp.js';
import { uuidv4, showSpinner, hideSpinner } from './js/common/components/utils.js';
import { initializeWebSocket } from './js/common/components/messageHandler.js';
import { updateWorkflowValue } from './js/common/components/workflowManager.js';
import { processWorkflowNodes } from './js/common/scripts/nodesscanner.js';
import { fetchWorkflow } from './js/common/scripts/fetchWorkflow.js';
import { fetchflowConfig } from './js/common/scripts/fetchflowConfig.js';
import { setFaviconStatus } from './js/common/scripts/favicon.js';
import { PreferencesManager } from './js/common/scripts/preferences.js';
import { initialize } from './js/common/scripts/interactiveUI.js';
import ThemeManager from './js/common/scripts/ThemeManager.js';
import injectStylesheet from './js/common/scripts/injectStylesheet.js';
import LoraWorkflowManager from './js/common/components/LoraWorkflowManager.js';
import { CanvasLoader } from './js/common/components/canvas/CanvasLoader.js';
import { checkAndShowMissingPackagesDialog } from './js/common/components/missingPackagesDialog.js';
import CanvasComponent from './js/common/components/CanvasComponent.js';
import { store } from './js/common/scripts/stateManagerMain.js';
(async (window, document, undefined) => {
const defaultPreferences = {
selectedCategories: [],
favoritesFilterActive: false,
hideDescriptions: false,
hideTitles: false,
sortValue: 'nameAsc',
selectedTheme: null
};
const preferencesManager = new PreferencesManager(defaultPreferences);
ThemeManager.applyInitialTheme(preferencesManager);
const themeManager = new ThemeManager(preferencesManager);
themeManager.init();
function getFlowName() {
const scripts = document.getElementsByTagName('script');
for (let script of scripts) {
if (script.src && script.src.includes('main.js')) {
try {
const url = new URL(script.src, window.location.origin);
const flowParam = url.searchParams.get('flow');
if (flowParam) {
console.log('Flow name from script src:', flowParam);
return flowParam;
}
} catch (e) {
console.error('Error parsing script src URL:', e);
}
}
}
const paths = window.location.pathname.split('/').filter(Boolean);
if (paths[0] === 'flow' && paths[1]) {
console.log('Flow name:', paths[1]);
return paths[1];
}
console.log('Default flow name: linker');
return 'linker';
}
const flowName = getFlowName();
const client_id = uuidv4();
const flowConfig = await fetchflowConfig(flowName);
let workflow = await fetchWorkflow(flowName);
let canvasLoader;
const seeders = [];
initializeWebSocket(client_id);
setFaviconStatus.Default();
injectStylesheet('/core/css/main.css', 'main');
injectStylesheet('/core/css/themes.css', 'themes-stylesheet');
console.log("flowConfig", flowConfig);
console.log("workflow", workflow);
function generateWorkflowControls(config) {
const container = document.getElementById('side-workflow-controls');
if (config.dropdowns && Array.isArray(config.dropdowns)) {
config.dropdowns.forEach(dropdown => {
const div = document.createElement('div');
div.id = dropdown.id;
div.classList.add('loader');
container.appendChild(div);
});
}
if (config.steppers && Array.isArray(config.steppers)) {
config.steppers.forEach(stepper => {
const div = document.createElement('div');
div.id = stepper.id;
div.classList.add('stepper-container');
container.appendChild(div);
});
}
if (config.dimensionSelectors) {
config.dimensionSelectors.forEach(selector => {
const div = document.createElement('div');
div.id = selector.id;
div.classList.add('dimension-selector-container');
container.appendChild(div);
});
}
if (config.inputs && Array.isArray(config.inputs)) {
config.inputs.forEach(input => {
const div = document.createElement('div');
div.id = input.id;
div.classList.add('input-container');
container.appendChild(div);
});
}
if (config.toggles && Array.isArray(config.toggles)) {
config.toggles.forEach(toggle => {
const div = document.createElement('div');
div.id = toggle.id;
div.classList.add('toggle-container');
container.appendChild(div);
});
}
if (config.seeders && Array.isArray(config.seeders)) {
config.seeders.forEach(seeder => {
const div = document.createElement('div');
div.id = seeder.id;
div.classList.add('seeder-container');
container.appendChild(div);
});
}
}
function setPromptComponents(config, options = { clearInputs: false }) {
if (!config.prompts || !Array.isArray(config.prompts)) {
return;
}
const promptsContainer = document.getElementById('prompts');
config.prompts.forEach((input, index) => {
const titleDiv = document.createElement('div');
titleDiv.id = 'prompt';
const labelDiv = document.createElement('div');
labelDiv.id = 'title-text';
labelDiv.textContent = input.label;
const textArea = document.createElement('textarea');
textArea.id = input.id;
if (options.clearInputs) {
textArea.value = '';
} else {
textArea.value = input.default || generateDynamicScriptDefault(index);
}
titleDiv.appendChild(labelDiv);
titleDiv.appendChild(textArea);
promptsContainer.appendChild(titleDiv);
});
}
function generateDynamicScriptDefault(index) {
const defaultsPrompts = [
'A cartoon cute happy white female goat with purple eyes and a black horn in the jungle',
'ugly, blur, jpeg artifacts, low quality, lowres, child',
];
return defaultsPrompts[index] || '';
}
generateWorkflowControls(flowConfig);
setPromptComponents(flowConfig, true);
const loraWorkflowManager = new LoraWorkflowManager(workflow, flowConfig);
workflow = loraWorkflowManager.getWorkflow();
processWorkflowNodes(workflow).then(({ nodeToCustomNodeMap, uniqueCustomNodesArray, missingNodes, missingCustomPackages }) => {
console.log("Node to Custom Node Mapping:", nodeToCustomNodeMap);
console.log("Unique Custom Nodes:", uniqueCustomNodesArray);
console.log("Missing Nodes:", missingNodes);
console.log("Missing Custom Packages:", missingCustomPackages);
checkAndShowMissingPackagesDialog(missingCustomPackages, missingNodes, flowConfig);
});
if (flowConfig.dropdowns) {
flowConfig.dropdowns.forEach(config => {
new Dropdown(config, workflow);
});
}
if (flowConfig.steppers) {
flowConfig.steppers.forEach(config => {
new Stepper(config, workflow);
});
}
if (flowConfig.dimensionSelectors) {
flowConfig.dimensionSelectors.forEach(config => {
new DimensionSelector(config, workflow);
});
}
if (flowConfig.inputs) {
flowConfig.inputs.forEach(config => {
new InputComponent(config, workflow);
});
}
if (flowConfig.toggles) {
flowConfig.toggles.forEach(config => {
new ToggleComponent(config, workflow);
});
}
if (flowConfig.seeders) {
flowConfig.seeders.forEach(config => {
const seeder = new Seeder(config, workflow);
seeders.push(seeder);
});
}
if (flowConfig.multiComponents && Array.isArray(flowConfig.multiComponents)) {
flowConfig.multiComponents.forEach(config => {
new MultiComponent(config, workflow);
});
}
if (flowConfig.dataComponents && Array.isArray(flowConfig.dataComponents)) {
flowConfig.dataComponents.forEach(config => {
new DataComponent(config, workflow);
});
}
imageLoaderComp(flowConfig, workflow);
const initCanvas = async () => {
canvasLoader = new CanvasLoader('imageCanvas', flowConfig);
await canvasLoader.initPromise;
if (canvasLoader.isInitialized) {
console.log("Canvas initialized successfully.");
const container = document.getElementById('pluginUIContainer');
const quickControls = document.getElementById('quick-controls');
container.append(quickControls);
} else {
console.log("Canvas was not initialized due to missing flowConfig fields.");
}
};
initCanvas();
async function queue() {
console.log("Queueing new job");
if (canvasLoader && canvasLoader.isInitialized) {
await CanvasComponent(flowConfig, workflow, canvasLoader);
} else {
console.log("Canvas is not initialized. Skipping CanvasComponent.");
}
console.log("Queueing workflow:", workflow);
if (flowConfig.prompts) {
flowConfig.prompts.forEach(pathConfig => {
const { id } = pathConfig;
const element = document.getElementById(id);
if (element) {
const value = element.value.replace(/(\r\n|\n|\r)/gm, " ");
updateWorkflowValue(workflow, id, value, flowConfig);
} else {
console.warn(`Element not found for ID: ${id}`);
}
});
}
const jobId = StateManager.incrementJobId();
const job = { id: jobId, workflow: { ...workflow } };
StateManager.addJob(job);
console.log(`Added job to queue. Job ID: ${jobId}`);
console.log("Current queue:", StateManager.getJobQueue());
console.log("queued workflow:", workflow);
store.dispatch({
type: 'SET_QUEUE_RUNNING',
payload: true
});
updateQueueDisplay(StateManager.getJobQueue());
if (!StateManager.isProcessing()) {
setTimeout(processQueue, 0);
}
}
async function processQueue() {
store.dispatch({
type: 'TOGGLE_MASK',
payload: true
});
if (StateManager.isProcessing()) return;
if (StateManager.getJobQueue().length === 0) {
return;
}
StateManager.setProcessing(true);
const job = StateManager.getNextJob();
console.log(`Processing job ${job.id}`);
try {
await queue_prompt(job.workflow);
} catch (error) {
console.error(`Error processing job ${job.id}:`, error);
StateManager.removeJob();
updateQueueDisplay(StateManager.getJobQueue());
StateManager.setProcessing(false);
processQueue();
}
}
async function queue_prompt(prompt = {}) {
showSpinner();
seeders.forEach(seeder => seeder.generateSeed());
const data = { 'prompt': prompt, 'client_id': client_id };
try {
const response = await fetch('/prompt', {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error('Failed to process prompt.');
}
// const result = await response.json();
} catch (error) {
console.error('Error processing prompt:', error);
throw error;
} finally {
// hideSpinner();
}
}
function updateQueueDisplay(jobQueue) {
const queueDisplay = document.getElementById('queue-display');
if (!queueDisplay) {
console.warn('queue-display element not found in the DOM.');
return;
}
if (jobQueue.length > 0) {
queueDisplay.textContent = `${jobQueue.length}`;
} else {
queueDisplay.textContent = '';
}
// if (jobQueue.length > 0) {
// const jobIds = jobQueue.map(job => job.id).join(', ');
// queueDisplay.textContent += ` (Job IDs: ${jobIds})`;
// }
}
async function interrupt() {
await queue_interrupt();
if (StateManager.isProcessing()) {
console.log("Interrupting current job");
} else if (StateManager.getJobQueue().length > 0) {
const removedJob = StateManager.getJobQueue().pop();
console.log(`Removed job from queue. Job ID: ${removedJob.id}`);
console.log("Remaining queue:", StateManager.getJobQueue());
updateQueueDisplay(StateManager.getJobQueue());
} else {
console.log("No jobs in queue to interrupt.");
}
}
async function queue_interrupt() {
console.log("Interrupting last job");
const data = { 'client_id': client_id };
try {
showSpinner();
const response = await fetch('/interrupt', {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error('Failed to interrupt the process.');
}
const result = await response.json();
console.log('Interrupted:', result);
} catch (error) {
console.error('Error during interrupt:', error);
hideSpinner();
} finally {
hideSpinner();
}
}
document.getElementById('generateButton').addEventListener('click', function () {
queue();
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
if (event.ctrlKey && event.altKey) {
interrupt();
event.preventDefault();
event.stopPropagation();
}
else if (event.ctrlKey) {
queue();
event.preventDefault();
event.stopPropagation();
}
}
});
document.getElementById('interruptButton').addEventListener('click', function () {
interrupt();
});
window.addEventListener('jobCompleted', () => {
StateManager.removeJob();
updateQueueDisplay(StateManager.getJobQueue());
StateManager.setProcessing(false);
processQueue();
});
window.addEventListener('jobInterrupted', () => {
StateManager.removeJob();
updateQueueDisplay(StateManager.getJobQueue());
StateManager.setProcessing(false);
processQueue();
});
document.addEventListener('DOMContentLoaded', () => {
initialize(false, false, false, false);
const overlay = document.getElementById('css-loading-overlay');
overlay.classList.add('fade-out');
overlay.addEventListener('transitionend', () => {
overlay.style.display = 'none';
});
});
})(window, document, undefined);