From ed90621ffb2355918f52b9027988d20b4edce9d8 Mon Sep 17 00:00:00 2001
From: Frankly George <54015-franklygeorge@users.noreply.gitgud.io>
Date: Sat, 23 Mar 2024 18:23:15 +0000
Subject: [PATCH] Add a queued images count to AI image settings.

---
 src/art/genAI/stableDiffusion.js | 23 +++++++++++++
 src/gui/options/options.js       | 59 +++++++++++++++++++++++++-------
 2 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/src/art/genAI/stableDiffusion.js b/src/art/genAI/stableDiffusion.js
index 5aef41d468e..6f51b6448a4 100644
--- a/src/art/genAI/stableDiffusion.js
+++ b/src/art/genAI/stableDiffusion.js
@@ -110,6 +110,25 @@ App.Art.GenAI.StableDiffusionClientQueue = class {
 		this.workingOnID = null;
 	}
 
+	/**
+	 * Updates the queue counts if on the ai image settings page
+	 */
+	updateQueueCounts() {
+		// update queue counts if on the page
+		["#mainQueueCount", "#backlogQueueCount"].forEach(queueElement => {
+			const queue = $(queueElement);
+			let count = 0;
+			if (queueElement === "#mainQueueCount") {
+				count = Math.max(0, this.queue.length - 1);
+			} else {
+				count = Math.max(0, this.backlogQueue.length - 1);
+			}
+			if (queue !== undefined && queue.length) {
+				queue.empty().append(count.toString());
+			}
+		});
+	}
+
 	/**
 	 * Process the top item in the queue, and continue processing the queue one at a time afterwards
 	 * @private
@@ -122,6 +141,8 @@ App.Art.GenAI.StableDiffusionClientQueue = class {
 			return false;
 		}
 
+		this.updateQueueCounts();
+
 		let top;
 		if (this.queue.length > 0) {
 			top = this.queue.shift();
@@ -239,6 +260,8 @@ App.Art.GenAI.StableDiffusionClientQueue = class {
 				});
 			}
 
+			this.updateQueueCounts();
+
 			this.process(); // do not await
 		});
 	}
diff --git a/src/gui/options/options.js b/src/gui/options/options.js
index 4abc6e8d5b3..8679db7d2ec 100644
--- a/src/gui/options/options.js
+++ b/src/gui/options/options.js
@@ -1,6 +1,6 @@
 // cSpell:ignore SSAA
 
-App.UI.optionsPassage = function () {
+App.UI.optionsPassage = function() {
 	const el = new DocumentFragment();
 	App.UI.DOM.appendNewElement("h1", el, `Game Options`);
 	App.Utils.PassageSwitchHandler.set(App.EventHandlers.optionsChanged);
@@ -9,12 +9,12 @@ App.UI.optionsPassage = function () {
 	try {
 		const tabBar = new App.UI.Tabs.TabBar("Options");
 		tabBar.addTab("Display", "display", App.Intro.display(false));
-		tabBar.addTab("Content & flavour", "content-flavor", App.Intro.contentAndFlavor(false));
+		tabBar.addTab("Content & Flavour", "content-flavor", App.Intro.contentAndFlavor(false));
 		tabBar.addTab("Mods", "mods", mods());
-		tabBar.addTab("Debug & cheating", "debug-cheating", debugCheating());
+		tabBar.addTab("Debug & Cheating", "debug-cheating", debugCheating());
 		if (V.cheatMode) {
 			tabBar.addTab("Cheats", "cheat", cheat());
-			tabBar.addTab("Cheat edit schools", "cheat-school", cheatSchools());
+			tabBar.addTab("Cheat Edit Schools", "cheat-school", cheatSchools());
 		}
 		tabBar.addTab("New Game Plus", "new-game-plus", newGamePlus());
 		tabBar.addTab("Experimental", "experimental", experimental());
@@ -27,6 +27,9 @@ App.UI.optionsPassage = function () {
 	}
 	return el;
 
+	/**
+	 * @returns {DocumentFragment} the header for the `Game Options` menu
+	 */
 	function intro() {
 		const el = new DocumentFragment();
 
@@ -49,6 +52,10 @@ App.UI.optionsPassage = function () {
 			App.UI.DOM.makeElement("span", `build: ${V.releaseID}.`, (V.releaseID !== App.Version.release) ? ["red"] : null)
 		]);
 
+		/**
+		 * Creates a html table row and fills it with contents
+		 * @param {any[]} contents
+		 */
 		function fillRow(contents) {
 			const row = App.UI.DOM.appendNewElement("tr", table);
 			for (const content of contents) {
@@ -111,6 +118,9 @@ App.UI.optionsPassage = function () {
 		return el;
 	}
 
+	/**
+	 * @returns {DocumentFragment} the contents of the `Mods` tab for the `Game Options` menu
+	 */
 	function mods() {
 		const el = new DocumentFragment();
 		let options;
@@ -394,6 +404,10 @@ App.UI.optionsPassage = function () {
 		} /* closes SecExp check*/
 		return el;
 
+		/**
+		 * creates a html table cell and returns it
+		 * @returns {HTMLTableCellElement}
+		 */
 		function createTd() {
 			const td = document.createElement("td");
 			td.style.columnSpan = "2";
@@ -413,6 +427,10 @@ App.UI.optionsPassage = function () {
 			]);
 
 			App.Mods.SecExp.unit.squads("human").forEach(u => u.loyalty = numberGenerator());
+			/**
+			 * returns a randomized value based off level and numberMap
+			 * @returns {number}
+			 */
 			function numberGenerator() {
 				const range = numberMap.get(level);
 				if (range[1]) {
@@ -424,6 +442,9 @@ App.UI.optionsPassage = function () {
 		}
 	}
 
+	/**
+	 * @returns {DocumentFragment} the contents of the `Cheats` tab for the `Game Options` menu
+	 */
 	function cheat() {
 		const el = new DocumentFragment();
 		const options = new App.UI.OptionsGroup();
@@ -439,6 +460,9 @@ App.UI.optionsPassage = function () {
 		return el;
 	}
 
+	/**
+	 * @returns {DocumentFragment} the contents of the `Cheat edit schools` tab for the `Game Options` menu
+	 */
 	function cheatSchools() {
 		const el = new DocumentFragment();
 		const options = new App.UI.OptionsGroup();
@@ -467,6 +491,9 @@ App.UI.optionsPassage = function () {
 		return el;
 	}
 
+	/**
+	 * @returns {DocumentFragment} the contents of the `Debug & cheating` tab for the `Game Options` menu
+	 */
 	function debugCheating() {
 		const el = new DocumentFragment();
 		let options;
@@ -698,6 +725,9 @@ App.UI.optionsPassage = function () {
 		return el;
 	}
 
+	/**
+	 * @returns {DocumentFragment} the contents of the `Experimental` tab for the `Game Options` menu
+	 */
 	function experimental() {
 		const el = new DocumentFragment();
 		let options;
@@ -772,6 +802,9 @@ App.UI.optionsPassage = function () {
 		return el;
 	}
 
+	/**
+	 * @returns {DocumentFragment} the contents of the `New Game Plus` tab for the `Game Options` menu
+	 */
 	function newGamePlus() {
 		const f = new DocumentFragment();
 		if ((V.releaseID >= 1000) || V.ver.startsWith("0.9") || V.ver.startsWith("0.8") || V.ver.startsWith("0.7") || V.ver.startsWith("0.6")) {
@@ -798,7 +831,7 @@ App.UI.optionsPassage = function () {
  * @param {boolean} isIntro
  * @returns {DocumentFragment}
  */
-App.Intro.display = function (isIntro) {
+App.Intro.display = function(isIntro) {
 	const el = new DocumentFragment();
 	let options;
 	let r;
@@ -956,7 +989,7 @@ App.Intro.display = function (isIntro) {
  * @param {boolean} isIntro
  * @returns {DocumentFragment}
  */
-App.Intro.contentAndFlavor = function (isIntro) {
+App.Intro.contentAndFlavor = function(isIntro) {
 	const el = new DocumentFragment();
 	let r;
 	let options;
@@ -1159,7 +1192,7 @@ App.Intro.contentAndFlavor = function (isIntro) {
 /**
  * @param {InstanceType<App.UI.OptionsGroup>} options
  */
-App.UI.aiPromptingOptions = function (options) {
+App.UI.aiPromptingOptions = function(options) {
 	options.addOption("NGBot's LoRA pack", "aiLoraPack")
 		.addValue("Enabled", true).on().addValue("Disabled", false).off()
 		.addComment("Adds prompting to support NGBot's LoRA pack; see the LoRA Pack Installation Guide for details");
@@ -1171,9 +1204,9 @@ App.UI.aiPromptingOptions = function (options) {
 			["Custom", 0]
 		]);
 	if (V.aiStyle === 0) {
-		options.addOption("AI custom style positive prompt", "aiCustomStylePos").showTextBox({ large: true, forceString: true })
+		options.addOption("AI custom style positive prompt", "aiCustomStylePos").showTextBox({large: true, forceString: true})
 			.addComment("Include desired LoRA triggers (<code>&lt;lora:LowRA:0.5&gt;</code>) and general style prompts relevant to your chosen model ('<code>hand drawn, dark theme, black background</code>'), but no slave-specific prompts");
-		options.addOption("AI custom style negative prompt", "aiCustomStyleNeg").showTextBox({ large: true, forceString: true })
+		options.addOption("AI custom style negative prompt", "aiCustomStyleNeg").showTextBox({large: true, forceString: true})
 			.addComment("Include undesired general style prompts relevant to your chosen model ('<code>greyscale, photography, forest, low camera angle</code>'), but no slave-specific prompts");
 	} else if (V.aiStyle === 1) {
 		options.addComment("For best results, use an appropriately-trained photorealistic base model, such as MajicMIX or Life Like Diffusion.");
@@ -1185,7 +1218,7 @@ App.UI.aiPromptingOptions = function (options) {
 		.addComment("Helps differentiate between ethnicities that share a Free Cities race, like Japanese and Korean or Spanish and Greek. May cause flags/national colors to appear unexpectedly, and can have a negative impact on slaves that belong to a minority race for their nationality.");
 };
 
-App.UI.artOptions = function () {
+App.UI.artOptions = function() {
 	const el = new DocumentFragment();
 	let options = new App.UI.OptionsGroup();
 
@@ -1504,9 +1537,11 @@ App.UI.artOptions = function () {
 						await App.Art.GenAI.sdQueue.resumeAfterInterrupt();
 					}
 					$("button:contains('Interrupt rendering')").removeClass("on selected disabled").addClass("off");
+					App.Art.GenAI.sdQueue.updateQueueCounts();
 				};
 				options.addCustomOption("Rendering Queue management")
-					.addButton("Interrupt rendering", () => renderQueueOption(true));
+					.addButton("Interrupt rendering and clear the rendering queues", () => renderQueueOption(true))
+					.addComment(`<span id="mainQueueCount">N/A</span> queued images in the main queue and <span id="backlogQueueCount">N/A</span> queued images in the backlog queue.`);
 				// adjust the state of the button when it is rendered
 				renderQueueOption();
 				options.addCustomOption("Cache database management")
@@ -1530,7 +1565,7 @@ App.UI.artOptions = function () {
 						}
 						console.log(`${App.Art.GenAI.sdQueue.queue.length} requests queued for rendering.`);
 					})
-					.addComment(`Current cache size: <span id="cacheCount">Please wait...</span>. The cache database is shared between games.`);
+					.addComment(`The cache database is shared between games. Current cache size: <span id="cacheCount">Please wait...</span>`);
 				if (V.aiCachingStrategy === 'static') {
 					App.Art.GenAI.staticImageDB.sizeInfo().then((result) => {
 						$("#cacheCount").empty().append(result);
-- 
GitLab