Finalized settings menu, improved search, some cleanup and improved handling of new yaml files.

This commit is contained in:
Dan
2024-09-09 00:59:07 -05:00
parent 23fb4e3d2b
commit 92c2fc23ff
+65 -146
View File
@@ -18,25 +18,19 @@ class PromptGallery {
this.useSelectedNodeCheckbox = this.createUseSelectedNodeCheckbox();
this.randomPromptButton = this.createRandomPromptButton();
this.categoryCheckboxes = new Map();
this.categories = [
"Art Styles", "Game Characters", "Show Characters",
"Female Body", "Poses", "Expressions", "Scenes"
];
/* this.categorySortOrder = this.yamlFiles.map(file => ({
name: file.type,
order: file.order
})); */
this.accordion = $el("div.prompt-accordion");
this.yamlFiles = [
{ name: "PonyXl-artstyles.yaml", type: "Art Styles", skipLevels: 0, sections: null, order: 1 },
{ name: "PonyXl-game_persona.yaml", type: "Game Characters", skipLevels: 0, sections: null, order: 2 },
{ name: "PonyXl-show_persona.yaml", type: "Show Characters", skipLevels: 0, sections: null, order: 3 },
{ name: "PonyXl-f-body.yaml", type: "Female Body", skipLevels: 0, sections: { body_race: "Race", body_form: "Build" }, order: 4 },
{ name: "PonyXl-poses.yaml", type: "Poses", skipLevels: 0, sections: null, order: 5 },
{ name: "PonyXl-expressions.yaml", type: "Expressions", skipLevels: 0, sections: null, order: 6, ignoreKey: "chara_expression" },
{ name: "PonyXl-scenes.yaml", type: "Scenes", skipLevels: 0, sections: null, order: 7 }
{ name: "PonyXl-poses.yaml", type: "Poses", skipLevels: 0, sections: null, order: 7 },
{ name: "PonyXl-expressions.yaml", type: "Expressions", skipLevels: 0, sections: null, order: 8, ignoreKey: "chara_expression" },
{ name: "PonyXl-scenes.yaml", type: "Scenes", skipLevels: 0, sections: null, order: 9 },
{ name: "PonyXl-jobs.yaml", type: "Jobs", skipLevels: 0, sections: null, order: 6 }
// will add more datasets here over time
];
this.categories = this.yamlFiles.map(file => file.type); // Derive categories from yamlFiles
this.baseUrl = `${window.location.protocol}//${window.location.host}`;
this.placeholderImageUrl = `${this.baseUrl}/prompt_gallery/image?filename=SKIP.jpeg`;
this.customImages = [];
@@ -45,6 +39,7 @@ class PromptGallery {
this.resetButton = this.createResetCustomImagesButton();
this.missingFiles = new Set();
// Initialize category order from YAML files
this.yamlFiles.forEach(file => {
const settingId = `Prompt Gallery.Category Order.${file.type.replace(/\s+/g, '')}`;
@@ -55,19 +50,17 @@ class PromptGallery {
});
// Initialize Female Body sub-categories
const femaleBodySubCategories = ["Build", "Race"];
const femaleBodyFile = this.yamlFiles.find(file => file.type === "Female Body");
if (femaleBodyFile) {
femaleBodySubCategories.forEach((subCategory, index) => {
if (femaleBodyFile && femaleBodyFile.sections) {
Object.values(femaleBodyFile.sections).forEach((subCategory, index) => {
const settingId = `Prompt Gallery.Category Order.FemaleBody_${subCategory}`;
const currentValue = this.app.ui.settings.getSettingValue(settingId, null);
if (currentValue === null) {
// Use index + 1 as a default order if you want sub-categories to be ordered after the main category
this.app.ui.settings.setSettingValue(settingId, femaleBodyFile.order + index + 1);
}
});
}
this.updateCategoryOrder();
const dropdownContainer = $el("div", {
@@ -141,7 +134,8 @@ class PromptGallery {
alignItems: "center",
marginLeft: "10px",
whiteSpace: "nowrap"
}
},
title: "Ignore dropdown setting and use the currently selected node as the target for prompt insertion."
});
const checkbox = $el("input", {
@@ -379,7 +373,7 @@ class PromptGallery {
const link = $el("a", {
href: "https://civitai.com/models/615967?modelVersionId=789576",
target: "_blank",
textContent: "Download Image Sets",
textContent: "New Image Sets to Download!",
style: {
color: "white",
textDecoration: "none",
@@ -432,7 +426,8 @@ class PromptGallery {
backgroundColor: "#2a2a2a",
color: "white",
textOverflow: "ellipsis"
}
},
title: "Select where the prompt will be inserted. Use Clipboard if you want to paste it yourself."
});
// to make the dropdown options use the full width
@@ -600,28 +595,19 @@ class PromptGallery {
}
updateCategoryOrder() {
//console.log("Updating category order");
const orderMap = new Map();
// Handle all categories and subcategories uniformly
this.categories.forEach(category => {
if (category === "Female Body") {
const subCategories = ["Build", "Race"];
subCategories.forEach(subCategory => {
const settingId = `Prompt Gallery.Category Order.FemaleBody_${subCategory}`;
const userOrder = this.app.ui.settings.getSettingValue(settingId, 0);
//console.log(`Female Body - ${subCategory}: userOrder = ${userOrder}`);
if (userOrder > 0) {
orderMap.set(`Female Body - ${subCategory}`, userOrder);
}
this.yamlFiles.forEach(file => {
const settingId = `Prompt Gallery.Category Order.${file.type.replace(/\s+/g, '')}`;
const userOrder = this.app.ui.settings.getSettingValue(settingId, file.order);
orderMap.set(file.type, userOrder);
if (file.sections) {
Object.values(file.sections).forEach(subCategory => {
const subSettingId = `Prompt Gallery.Category Order.${file.type.replace(/\s+/g, '')}_${subCategory}`;
const subUserOrder = this.app.ui.settings.getSettingValue(subSettingId, userOrder);
orderMap.set(`${file.type} - ${subCategory}`, subUserOrder);
});
} else {
const settingId = `Prompt Gallery.Category Order.${category.replace(/\s+/g, '')}`;
const userOrder = this.app.ui.settings.getSettingValue(settingId, 0);
//console.log(`${category}: userOrder = ${userOrder}`);
if (userOrder > 0) {
orderMap.set(category, userOrder);
}
}
});
@@ -629,8 +615,6 @@ class PromptGallery {
.sort((a, b) => a[1] - b[1] || a[0].localeCompare(b[0]))
.map(([name]) => name);
//console.log("Updated category order:", this.categorySortOrder);
this.update();
}
@@ -758,7 +742,6 @@ class PromptGallery {
return metadata;
} catch (error) {
console.error(`Error in fetchImageMetadata: ${error.message}`);
console.error(error.stack); // Log the full error stack
throw error;
}
}
@@ -1056,16 +1039,18 @@ class PromptGallery {
searchTerm = searchTerm.toLowerCase();
this.isSearchActive = searchTerm.length > 0;
this.filteredImages = this.allImages.filter(image =>
image && image.name && image.name.toLowerCase().includes(searchTerm)
(image && image.name && image.name.toLowerCase().includes(searchTerm)) ||
(image && image.subcategory && image.subcategory.toLowerCase().includes(searchTerm))
);
// Filter custom images
this.filteredCustomImages = this.customImages.filter(image =>
image && image.name && image.name.toLowerCase().includes(searchTerm)
(image && image.name && image.name.toLowerCase().includes(searchTerm)) ||
(image && image.subcategory && image.subcategory.toLowerCase().includes(searchTerm))
);
this.sortAndDisplayImages();
}
flattenAllImages() {
/* flattenAllImages() {
return this.allImages.flatMap(category => {
if (Array.isArray(category.images)) {
return category.images;
@@ -1076,7 +1061,7 @@ class PromptGallery {
}
return [];
});
}
} */
groupImagesByType(images) {
return images.reduce((acc, image) => {
@@ -1262,9 +1247,7 @@ class PromptGallery {
const nextLine = lines[index + 1];
if (nextLine && nextLine.trim().startsWith('-')) {
let path = stack.slice(skipLevels, -1).map(item => item.key).join('/');
// Remove any duplicate 'ponyxl' in the path
path = path.replace(/^ponyxl\//, '');
path = path.replace(/^ponyxl\//, ''); // Remove any duplicate 'ponyxl' in the path
const tags = nextLine.trim().substring(1).trim();
@@ -1290,7 +1273,11 @@ class PromptGallery {
const subfolderPath = `ponyxl/${path}`;
const imageUrl = `${this.baseUrl}/prompt_gallery/image?filename=${encodeURIComponent(imageFilename)}&subfolder=${encodeURIComponent(subfolderPath)}`;
const image = { name: key, path: imageUrl, tags: tags, type: type };
// Get the immediate parent category (one level up)
const pathParts = path.split('/');
const immediateParent = pathParts[pathParts.length - 1];
const image = { name: key, path: imageUrl, tags: tags, type: type, subcategory: immediateParent };
if (sections) {
for (const [sectionKey, sectionName] of Object.entries(sections)) {
@@ -1694,70 +1681,6 @@ class PromptGallery {
});
}
// I'm going to try and make a new UI for the SETTINGS page, wish me luck
createCategorySortUI() {
const container = $el("div", {
className: "category-sort-container",
style: {
marginTop: "10px",
border: "1px solid #ccc",
padding: "10px",
borderRadius: "5px"
}
});
const title = $el("h3", {
textContent: "Category Sort Order",
style: {
marginBottom: "10px"
}
});
container.appendChild(title);
const list = $el("ul", {
className: "category-sort-list",
style: {
listStyle: "none",
padding: 0
}
});
this.categorySortOrder.forEach(category => {
if (category !== "Custom") {
const item = $el("li", {
textContent: category,
draggable: true,
style: {
padding: "5px",
marginBottom: "5px",
backgroundColor: "#2a2a2a",
cursor: "move"
}
});
item.addEventListener("dragstart", e => {
e.dataTransfer.setData("text/plain", category);
});
item.addEventListener("dragover", e => {
e.preventDefault();
});
item.addEventListener("drop", e => {
e.preventDefault();
const draggedCategory = e.dataTransfer.getData("text");
const newOrder = this.categorySortOrder.filter(c => c !== draggedCategory);
const dropIndex = newOrder.indexOf(category);
newOrder.splice(dropIndex, 0, draggedCategory);
this.updateCategorySortOrder(newOrder);
this.createCategorySortUI(); // Recreate the UI with the new order
// app.ui.settings.updateSettingValue("Prompt Gallery.Category.categorySortOrder", newOrder.join(',')); - Need to refactor this
});
list.appendChild(item);
}
});
container.appendChild(list);
return container;
}
}
app.registerExtension({
@@ -1788,41 +1711,20 @@ app.registerExtension({
},
});
const categories = [
"Art Styles", "Game Characters", "Show Characters",
"Female Body", "Poses", "Expressions", "Scenes"
];
const gallery = new PromptGallery(app);
app.promptGallery = gallery;
// Sort categories alphabetically for the settings page
const sortedCategories = [...categories].sort((a, b) => b.localeCompare(a));
// Sort yamlFiles by type for alphabetical order
const sortedYamlFiles = [...gallery.yamlFiles].sort((a, b) => b.type.localeCompare(a.type));
sortedCategories.forEach((category) => {
if (category === "Female Body") {
const subCategories = ["Build", "Race"];
subCategories.forEach((subCategory, index) => {
const settingId = `Prompt Gallery.Category Order.FemaleBody_${subCategory}`;
app.ui.settings.addSetting({
id: settingId,
name: `${category} - ${subCategory}`,
type: "number",
defaultValue: 0,
min: 0,
step: 1,
onChange: (newVal, oldVal) => {
//console.log(`${category} - ${subCategory} Order changed from ${oldVal} to ${newVal}, saved as ${settingId}`);
if (app.promptGallery) {
app.promptGallery.updateCategoryOrder();
}
},
});
});
} else {
const settingId = `Prompt Gallery.Category Order.${category.replace(/\s+/g, '')}`;
sortedYamlFiles.forEach((file) => {
if (file.type !== "Female Body") {
const settingId = `Prompt Gallery.Category Order.${file.type.replace(/\s+/g, '')}`;
app.ui.settings.addSetting({
id: settingId,
name: `${category}`,
name: `${file.type}`,
type: "number",
defaultValue: 0, // We'll set the actual default in the PromptGallery constructor
defaultValue: file.order,
min: 0,
step: 1,
onChange: (newVal, oldVal) => {
@@ -1832,10 +1734,27 @@ app.registerExtension({
},
});
}
});
const gallery = new PromptGallery(app);
app.promptGallery = gallery;
// Handle subcategories (sections) if they exist
if (file.sections) {
Object.entries(file.sections).forEach(([key, subCategory]) => {
const subSettingId = `Prompt Gallery.Category Order.${file.type.replace(/\s+/g, '')}_${subCategory}`;
app.ui.settings.addSetting({
id: subSettingId,
name: `${file.type} - ${subCategory}`,
type: "number",
defaultValue: file.order,
min: 0,
step: 1,
onChange: (newVal, oldVal) => {
if (app.promptGallery) {
app.promptGallery.updateCategoryOrder();
}
},
});
});
}
});
// Registering the sidebar tab
app.extensionManager.registerSidebarTab({