kingkont 0.8.5 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.html +0 -3
- package/package.json +1 -1
- package/renderer/board.js +46 -0
- package/renderer/generate.js +5 -18
package/index.html
CHANGED
|
@@ -238,9 +238,6 @@
|
|
|
238
238
|
<button data-act="audio">🎙 Сгенерировать голос</button>
|
|
239
239
|
<button data-act="image">🖼 Сгенерировать картинку</button>
|
|
240
240
|
<button data-act="video">🎬 Сгенерировать видео</button>
|
|
241
|
-
<hr style="margin:4px 0; border:0; border-top:1px solid #333;">
|
|
242
|
-
<button data-act="save-template" title="Загрузить эту сцену как шаблон на сервер">💾 Сохранить сцену как шаблон</button>
|
|
243
|
-
<button data-act="save-project-template" title="Загрузить весь проект (все сцены/персонажи/локации) как шаблон">💾 Сохранить проект как шаблон</button>
|
|
244
241
|
</div>
|
|
245
242
|
|
|
246
243
|
<!-- ===== Settings modal (двойной клик на сгенерированную ноду) ===== -->
|
package/package.json
CHANGED
package/renderer/board.js
CHANGED
|
@@ -52,6 +52,12 @@ window.addEventListener('DOMContentLoaded', async () => {
|
|
|
52
52
|
$('openTemplates')?.addEventListener('click', () => {
|
|
53
53
|
if (typeof openTemplatesWindow === 'function') openTemplatesWindow();
|
|
54
54
|
});
|
|
55
|
+
// ПКМ на 📚 — действия над всем проектом (сохранение проекта как шаблон).
|
|
56
|
+
$('openTemplates')?.addEventListener('contextmenu', e => {
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
e.stopPropagation();
|
|
59
|
+
showTemplatesButtonContextMenu(e.clientX, e.clientY);
|
|
60
|
+
});
|
|
55
61
|
// Sidebar search — фильтрует персонажей/локации/сцены.
|
|
56
62
|
$('sidebarSearch').addEventListener('input', e => {
|
|
57
63
|
const q = e.target.value.trim().toLowerCase();
|
|
@@ -751,6 +757,21 @@ function showBoardContextMenu(kind, item, clientX, clientY) {
|
|
|
751
757
|
selectBoard({ kind, ...item }).then(() => openCharacterSettings()).catch(() => {});
|
|
752
758
|
});
|
|
753
759
|
}
|
|
760
|
+
// Сохранение этого board'а как шаблон. saveCurrentBoardAsTemplate
|
|
761
|
+
// работает с state.currentBoard, поэтому сначала открываем нужный
|
|
762
|
+
// board (если он не текущий), а затем запускаем сохранение.
|
|
763
|
+
add('💾 Сохранить как шаблон', async () => {
|
|
764
|
+
try {
|
|
765
|
+
if (!state.currentBoard || state.currentBoard.kind !== kind || state.currentBoard.name !== item.name) {
|
|
766
|
+
await selectBoard({ kind, ...item });
|
|
767
|
+
}
|
|
768
|
+
if (typeof saveCurrentBoardAsTemplate === 'function') {
|
|
769
|
+
await saveCurrentBoardAsTemplate();
|
|
770
|
+
}
|
|
771
|
+
} catch (e) {
|
|
772
|
+
alert('Не удалось сохранить как шаблон: ' + (e?.message || e));
|
|
773
|
+
}
|
|
774
|
+
});
|
|
754
775
|
add('🗑 Удалить', async () => {
|
|
755
776
|
if (!confirm(`Удалить «${item.name}»? Папка переедет в _deleted, Cmd+Z восстановит.`)) return;
|
|
756
777
|
try { await deleteBoard(kind, item.name); }
|
|
@@ -1986,6 +2007,31 @@ function showNodeContextMenu(node, clientX, clientY) {
|
|
|
1986
2007
|
setTimeout(() => document.addEventListener('mousedown', closeNodeMenu, { once: true }), 0);
|
|
1987
2008
|
}
|
|
1988
2009
|
|
|
2010
|
+
// ПКМ на 📚 Templates-кнопке — действия проектного уровня.
|
|
2011
|
+
function showTemplatesButtonContextMenu(clientX, clientY) {
|
|
2012
|
+
const menu = $('nodeMenu');
|
|
2013
|
+
menu.innerHTML = '';
|
|
2014
|
+
const add = (label, fn, opts = {}) => {
|
|
2015
|
+
const b = document.createElement('button');
|
|
2016
|
+
b.textContent = label;
|
|
2017
|
+
if (opts.disabled) { b.disabled = true; b.style.opacity = '0.4'; b.style.cursor = 'default'; }
|
|
2018
|
+
b.addEventListener('click', () => {
|
|
2019
|
+
if (b.disabled) return;
|
|
2020
|
+
menu.classList.add('hidden');
|
|
2021
|
+
fn();
|
|
2022
|
+
});
|
|
2023
|
+
menu.appendChild(b);
|
|
2024
|
+
};
|
|
2025
|
+
add('📂 Открыть библиотеку шаблонов', () => {
|
|
2026
|
+
if (typeof openTemplatesWindow === 'function') openTemplatesWindow();
|
|
2027
|
+
});
|
|
2028
|
+
add('💾 Сохранить проект как шаблон', () => {
|
|
2029
|
+
if (typeof saveCurrentProjectAsTemplate === 'function') saveCurrentProjectAsTemplate();
|
|
2030
|
+
}, { disabled: !state.filmHandle });
|
|
2031
|
+
positionFloatingMenu(menu, clientX, clientY);
|
|
2032
|
+
setTimeout(() => document.addEventListener('mousedown', closeNodeMenu, { once: true }), 0);
|
|
2033
|
+
}
|
|
2034
|
+
|
|
1989
2035
|
function closeNodeMenu(e) {
|
|
1990
2036
|
// Клик по активной кнопке меню — даём её click-обработчику сработать (он сам закроет меню),
|
|
1991
2037
|
// а пока перевзводим listener, чтобы случайно не закрыть до click-а.
|
package/renderer/generate.js
CHANGED
|
@@ -158,24 +158,11 @@ document.querySelectorAll('#addMenu button').forEach(btn => {
|
|
|
158
158
|
state.addMenuPos = null;
|
|
159
159
|
return;
|
|
160
160
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (typeof saveCurrentBoardAsTemplate === 'function') {
|
|
167
|
-
await saveCurrentBoardAsTemplate();
|
|
168
|
-
}
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (act === 'save-project-template') {
|
|
172
|
-
// Сохранение ВСЕГО проекта (все boards) как одного шаблона.
|
|
173
|
-
state.addMenuPos = null;
|
|
174
|
-
if (typeof saveCurrentProjectAsTemplate === 'function') {
|
|
175
|
-
await saveCurrentProjectAsTemplate();
|
|
176
|
-
}
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
161
|
+
// save-template actions перенесены:
|
|
162
|
+
// • «Сохранить сцену как шаблон» — ПКМ на board-item в sidebar
|
|
163
|
+
// (см. showBoardContextMenu в board.js)
|
|
164
|
+
// • «Сохранить проект как шаблон» — ПКМ на 📚 Templates-кнопке
|
|
165
|
+
// (см. showTemplatesButtonContextMenu в board.js)
|
|
179
166
|
if (act === 'gen-text') {
|
|
180
167
|
// открываем text-gen modal; если есть fromNode — подставляем @ref в промпт
|
|
181
168
|
if (!await ensureApiKey('text')) return;
|