226 lines
7.7 KiB
TypeScript
226 lines
7.7 KiB
TypeScript
const TAB_PREFIX_LIST = ['txt2img', 'img2img'];
|
|
const MODEL_TYPE_LIST: ['textual_inversion', 'hypernetworks', 'checkpoints', 'lora', 'lycoris'] = [
|
|
'textual_inversion',
|
|
'hypernetworks',
|
|
'checkpoints',
|
|
'lora',
|
|
'lycoris',
|
|
];
|
|
const MODEL_TYPE = {
|
|
checkpoints: 'ckp',
|
|
hypernetworks: 'hyper',
|
|
lora: 'lora',
|
|
lycoris: 'lycoris',
|
|
textual_inversion: 'ti',
|
|
};
|
|
const CARDID_SUFFIX = 'cards';
|
|
|
|
// CSS
|
|
const BTN_MARGIN = '0';
|
|
const BTN_FONT_SIZE = '15px';
|
|
const BTN_THUMB_FONT_SIZE = '100%';
|
|
const BTN_THUMB_DISPLAY = 'inline';
|
|
const BTN_THUMB_POS = 'static';
|
|
const BTN_THUMB_BACKGROUND_IMAGE = 'none';
|
|
const BTN_THUMB_BACKGROUND = 'rgba(0, 0, 0, 0.8)';
|
|
const CH_BTN_TXTS = new Set(['🌐', '💡', '🏷️']);
|
|
|
|
const styleButton = (node: HTMLElement, isThumbMode: boolean) => {
|
|
if (isThumbMode) {
|
|
node.style.display = BTN_THUMB_DISPLAY;
|
|
node.style.fontSize = BTN_THUMB_FONT_SIZE;
|
|
node.style.position = BTN_THUMB_POS;
|
|
node.style.backgroundImage = BTN_THUMB_BACKGROUND_IMAGE;
|
|
} else {
|
|
node.style.fontSize = BTN_FONT_SIZE;
|
|
node.style.margin = BTN_MARGIN;
|
|
}
|
|
};
|
|
|
|
const updateCardForCivitai = () => {
|
|
if (!document.querySelector('#tab_civitai_helper')) return;
|
|
|
|
const replacePreviewText = getTranslation('replace preview') || 'replace preview';
|
|
|
|
// Get component
|
|
const chAlwaysDisplayCkb = document.querySelector(
|
|
'#ch_always_display_ckb input',
|
|
) as HTMLInputElement;
|
|
const chShowButtonOnThumbCkb = document.querySelector(
|
|
'#ch_show_btn_on_thumb_ckb input',
|
|
) as HTMLInputElement;
|
|
const chAlwaysDisplay = chAlwaysDisplayCkb?.checked || false;
|
|
const chShowButtonOnThumb = chShowButtonOnThumbCkb?.checked || false;
|
|
|
|
// Change all "replace preview" into an icon
|
|
let extraNetworkId = '';
|
|
let extraNetworkNode: any;
|
|
let metadataButton: any;
|
|
let additionalNode: any;
|
|
let replacePreviewButton: any;
|
|
let ulNode: any;
|
|
let searchTermNode: any;
|
|
let searchTerm = '';
|
|
let modelType = '';
|
|
let cards;
|
|
let needToAddButtons = false;
|
|
let isThumbMode = false;
|
|
|
|
// Get current tab
|
|
for (const activeTabType of TAB_PREFIX_LIST) {
|
|
for (const jsModelType of MODEL_TYPE_LIST) {
|
|
modelType = MODEL_TYPE[jsModelType];
|
|
// Get model_type for python side
|
|
|
|
extraNetworkId = `${activeTabType}_${jsModelType}_${CARDID_SUFFIX}`;
|
|
extraNetworkNode = document.querySelector(`#${extraNetworkId}`);
|
|
|
|
// Check if extra network node exists
|
|
if (extraNetworkNode === undefined) continue;
|
|
|
|
// Check if extr network is under thumbnail mode
|
|
isThumbMode = false;
|
|
if (extraNetworkNode?.className === 'extra-network-thumbs') isThumbMode = true;
|
|
|
|
// Get all card nodes
|
|
cards = extraNetworkNode?.querySelectorAll('.card');
|
|
if (!cards) continue;
|
|
for (const card of cards) {
|
|
if (card.querySelectorAll('.actions .additional a').length > 2) continue;
|
|
// Metadata_buttoncard
|
|
metadataButton = card.querySelector('.metadata-button');
|
|
// Additional node
|
|
additionalNode = card.querySelector('.actions .additional');
|
|
|
|
// Get ul node, which is the parent of all buttons
|
|
ulNode = card.querySelector('.actions .additional ul');
|
|
if (ulNode === undefined) {
|
|
ulNode = document.createElement('ul');
|
|
additionalNode.append(ulNode);
|
|
}
|
|
|
|
// Replace preview text button
|
|
replacePreviewButton = card.querySelector('.actions .additional a');
|
|
if (replacePreviewButton === undefined) {
|
|
replacePreviewButton = document.createElement('a');
|
|
additionalNode.append(replacePreviewButton);
|
|
}
|
|
|
|
// Check thumb mode
|
|
if (isThumbMode && additionalNode) {
|
|
additionalNode.style.display = undefined;
|
|
|
|
if (chShowButtonOnThumb) {
|
|
ulNode.style.background = BTN_THUMB_BACKGROUND;
|
|
} else {
|
|
// Reset
|
|
ulNode.style.background = undefined;
|
|
// Remove existed buttons
|
|
if (ulNode) {
|
|
// Find all .a child nodes
|
|
const atags = ulNode?.querySelectorAll('a');
|
|
if (!atags) continue;
|
|
for (const atag of atags) {
|
|
// Reset display
|
|
atag.style.display = undefined;
|
|
// Remove extension's button
|
|
if (CH_BTN_TXTS.has(atag.innerHTML)) {
|
|
// Need to remove
|
|
atag.remove();
|
|
} else {
|
|
// Do not remove, just reset
|
|
atag.innerHTML = replacePreviewText;
|
|
atag.style.display = undefined;
|
|
atag.style.fontSize = undefined;
|
|
atag.style.position = undefined;
|
|
atag.style.backgroundImage = undefined;
|
|
}
|
|
}
|
|
|
|
// Also remove br tag in ul
|
|
const brtag = ulNode.querySelector('br');
|
|
if (brtag) brtag.remove();
|
|
}
|
|
// Just reset and remove nodes, do nothing else
|
|
continue;
|
|
}
|
|
} else {
|
|
// Full preview mode
|
|
additionalNode.style.display = chAlwaysDisplay ? 'block' : undefined;
|
|
|
|
// Remove br tag
|
|
const brtag = ulNode.querySelector('br');
|
|
if (brtag) brtag.remove();
|
|
}
|
|
|
|
// Change replace preview text button into icon
|
|
if (replacePreviewButton?.innerHTML !== '🖼️') {
|
|
needToAddButtons = true;
|
|
replacePreviewButton.innerHTML = '🖼️';
|
|
styleButton(replacePreviewButton, isThumbMode);
|
|
}
|
|
|
|
if (!needToAddButtons) continue;
|
|
// Search_term node
|
|
// Search_term = subfolder path + model name + ext
|
|
searchTermNode = card.querySelector('.actions .additional .search_term');
|
|
if (!searchTermNode) return;
|
|
// Get search_term
|
|
searchTerm = searchTermNode.innerHTML;
|
|
if (!searchTerm) continue;
|
|
|
|
// Then we need to add 3 buttons to each ul node:
|
|
const openUrlNode = document.createElement('a');
|
|
openUrlNode.href = '#';
|
|
openUrlNode.innerHTML = '🌐';
|
|
styleButton(openUrlNode, isThumbMode);
|
|
openUrlNode.title = "Open this model's civitai url";
|
|
openUrlNode.setAttribute(
|
|
'onclick',
|
|
`open_model_url(event, '${modelType}', '${searchTerm}')`,
|
|
);
|
|
|
|
const addTriggerWordsNode = document.createElement('a');
|
|
addTriggerWordsNode.href = '#';
|
|
addTriggerWordsNode.innerHTML = '💡';
|
|
styleButton(addTriggerWordsNode, isThumbMode);
|
|
addTriggerWordsNode.title = 'Add trigger words to prompt';
|
|
addTriggerWordsNode.setAttribute(
|
|
'onclick',
|
|
`add_trigger_words(event, '${modelType}', '${searchTerm}')`,
|
|
);
|
|
|
|
const usePreviewPromptNode = document.createElement('a');
|
|
usePreviewPromptNode.href = '#';
|
|
usePreviewPromptNode.innerHTML = '🏷️';
|
|
styleButton(usePreviewPromptNode, isThumbMode);
|
|
usePreviewPromptNode.title = 'Use prompt from preview image';
|
|
usePreviewPromptNode.setAttribute(
|
|
'onclick',
|
|
`use_preview_prompt(event, '${modelType}', '${searchTerm}')`,
|
|
);
|
|
|
|
// Add to card
|
|
ulNode.append(openUrlNode);
|
|
// Add br if metadata_button exists
|
|
if (isThumbMode && metadataButton) ulNode.append(document.createElement('br'));
|
|
ulNode.append(addTriggerWordsNode);
|
|
ulNode.append(usePreviewPromptNode);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
export default () => {
|
|
let retryTimes = 0;
|
|
const fixInterval = setInterval(() => {
|
|
console.debug('🤯 [civitai helper] update card for civitai');
|
|
const checkDom = document.querySelector('#txt2img_lora_cards');
|
|
if (checkDom || retryTimes > 10) {
|
|
updateCardForCivitai();
|
|
clearInterval(fixInterval);
|
|
}
|
|
retryTimes++;
|
|
}, 1000);
|
|
};
|