Files
da2el-ai-D2-nodes-ComfyUI/web/D2_QueueButton.js
T
2024-10-19 12:29:02 +09:00

245 lines
6.6 KiB
JavaScript

import { app } from "../../scripts/app.js";
const D2_QUEUE_DEFAULT_COUNT = "1,10";
/**
* Queue Button を作るクラス
*/
class D2_QueueButton {
static CSS_FILEPATH = "./extensions/D2-nodes-ComfyUI/css/D2_QueueButton.css";
static COOKIE_NAME = "D2_QueueButton_Pos";
static DEFAULT_LEFT = 50;
static DEFAULT_TOP = 50;
container = undefined;
buttonContainer = undefined;
constructor() {
D2_QueueButton._loadStyles();
this._createContainer();
this._createButtons();
// 表示切り替え
const visible = app.ui.settings.getSettingValue("D2.QueueButton.Visible", true);
this.changeVisible(visible);
// 初期位置
const pos = D2_QueueButton._getPosition();
this.container.style.left = pos[0] + "px";
this.container.style.top = pos[1] + "px";
// ウィンドウリサイズ対策
window.addEventListener("resize", () => {
this.resizeSetting();
});
this.resizeSetting();
}
/**
* ボタンリセット
*/
resetButton() {
this.buttonContainer.innerHTML = "";
this._createButtons();
}
/**
* 表示切り替え
*/
changeVisible(bool) {
this.container.style.display = bool ? "block" : "none";
}
///////////////////////////////////////////////
// private method
///////////////////////////////////////////////
/**
* ベース作成
*/
_createContainer() {
this.container = document.createElement("div");
this.container.classList.add("p-panel", "d2-queue-button");
document.querySelector("body").appendChild(this.container);
const content = document.createElement("div");
content.classList.add("p-panel-content", "flex", "flex-nowrap", "items-center", "d2-queue-button__content");
this.container.appendChild(content);
const dragHandle = document.createElement("span");
dragHandle.classList.add("drag-handle", "cursor-move", "mr-2");
content.appendChild(dragHandle);
this.buttonContainer = document.createElement("div");
this.buttonContainer.classList.add("flex", "flex-nowrap", "items-center", "d2-queue-button__button-container");
content.appendChild(this.buttonContainer);
// ドラッグ設定
this._dragSetting(dragHandle, this.container);
}
/**
* ボタン作成
*/
_createButtons() {
const counts = D2_QueueButton._getCounts();
counts.forEach((count) => {
const button = document.createElement("button");
button.classList.add("p-button");
button.textContent = count;
this.buttonContainer.appendChild(button);
button.addEventListener("click", function (event) {
app.queuePrompt(event.shiftKey ? -1 : 0, count);
});
});
}
/**
* 設定からボタン設定を読む
*/
static _getCounts(string) {
const setting = app.ui.settings.getSettingValue("D2.QueueButton.BatchCount", D2_QUEUE_DEFAULT_COUNT);
if (setting.trim() === "") return [];
return setting
.split(",")
.map((item) => item.trim())
.filter((item) => item !== "")
.map((item) => Number(item));
}
/**
* CSSを動的に読み込む
*/
static _loadStyles() {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = D2_QueueButton.CSS_FILEPATH;
document.head.appendChild(link);
}
/**
* 座標をcookieに記録
*/
static _savePosition(x, y) {
const jsonString = JSON.stringify([x, y]);
const encodedJsonString = encodeURIComponent(jsonString);
const farFuture = new Date();
farFuture.setFullYear(farFuture.getFullYear() + 100);
document.cookie = `${D2_QueueButton.COOKIE_NAME}=${encodedJsonString}; expires=${farFuture.toUTCString()}; path=/`;
}
/**
* 座標をcookieから取得
*/
static _getPosition() {
const cookies = document.cookie.split(";");
for (let cookie of cookies) {
cookie = cookie.trim();
if (cookie.startsWith(D2_QueueButton.COOKIE_NAME + "=")) {
const encodedJsonString = cookie.substring(D2_QueueButton.COOKIE_NAME.length + 1);
const jsonString = decodeURIComponent(encodedJsonString);
return JSON.parse(jsonString);
}
}
// Cookieが見つからない場合
return [D2_QueueButton.DEFAULT_LEFT, D2_QueueButton.DEFAULT_TOP];
}
/**
* ドラッグ設定
*/
_dragSetting(handle, container) {
let isDragging = false;
let startX, startY, initialLeft, initialTop;
// マウスダウンイベントリスナー
handle.addEventListener("mousedown", (e) => {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
initialLeft = container.offsetLeft;
initialTop = container.offsetTop;
// テキスト選択を防止
e.preventDefault();
});
// マウスムーブイベントリスナー
document.addEventListener("mousemove", (e) => {
if (!isDragging) return;
const x = e.clientX - startX + initialLeft;
const y = e.clientY - startY + initialTop;
container.style.left = `${x}px`;
container.style.top = `${y}px`;
D2_QueueButton._savePosition(x, y);
});
// マウスアップイベントリスナー
document.addEventListener("mouseup", () => {
isDragging = false;
});
// マウスリーブイベントリスナー(ブラウザ外にマウスが出た場合)
document.addEventListener("mouseleave", () => {
isDragging = false;
});
}
/**
* ウィンドウリサイズ対策
*/
resizeSetting() {
const container = this.container;
const rect = container.getBoundingClientRect();
const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
// 右端の調整
if (rect.right > viewportWidth) {
const newLeft = Math.max(0, viewportWidth - rect.width);
container.style.left = `${newLeft}px`;
} else if (rect.left < 0) {
container.style.left = '0px';
}
// 下端の調整
if (rect.bottom > viewportHeight) {
const newTop = Math.max(0, viewportHeight - rect.height);
container.style.top = `${newTop}px`;
} else if (rect.top < 0) {
container.style.top = '0px';
}
}
}
(function () {
const queueButton = new D2_QueueButton();
app.ui.settings.addSetting({
id: "D2.QueueButton.BatchCount",
name: "Batch count list",
type: "string",
defaultValue: D2_QUEUE_DEFAULT_COUNT,
onChange(value) {
queueButton.resetButton();
},
});
app.ui.settings.addSetting({
id: "D2.QueueButton.Visible",
name: "Show queue button",
type: "boolean",
defaultValue: true,
onChange(value) {
queueButton.changeVisible(value);
},
});
})();