reorder
This commit is contained in:
@@ -126,6 +126,19 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.image-card.highlight-prev {
|
||||
border: 2px solid #f59e0b !important;
|
||||
box-shadow: 0 0 15px rgba(245, 158, 11, 0.4);
|
||||
}
|
||||
|
||||
.pad-preview-overlay {
|
||||
position: absolute;
|
||||
background: rgba(245,158,11,0.25);
|
||||
border: 1px dashed #f59e0b;
|
||||
pointer-events: none;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
background: rgba(0,0,0,0.6);
|
||||
backdrop-filter: blur(4px);
|
||||
@@ -1902,6 +1915,7 @@
|
||||
<div class="studio-topbar">
|
||||
<div class="studio-topbar-left">
|
||||
<button class="btn" onclick="closeStudio()" style="font-size:11px;padding:4px 10px">✕ Gallery</button>
|
||||
<button class="btn" id="lbBackBtn" onclick="jumpToPrevGroup()" style="font-size:11px;padding:4px 10px;display:none" title="Go back to previously opened group">↺ Back</button>
|
||||
</div>
|
||||
<div class="studio-topbar-center">
|
||||
<input type="text" id="lbGroupNameInput"
|
||||
@@ -2426,8 +2440,11 @@
|
||||
let currentFiles = [];
|
||||
let currentGroups = [];
|
||||
const groupData = new Map(); // gid → { urls[], names[] }
|
||||
const fileGroups = {}; // filename → gid (for jumpToImage)
|
||||
const cycleTimers = new Map(); // gid → intervalId
|
||||
const cycleIdx = new Map(); // gid → current index
|
||||
let _lastSelectedGid = localStorage.getItem('lastSelectedGid') || null;
|
||||
let _prevGid = null; // for "Back" button in studio
|
||||
let imageNames = {}; // filename → human name (from /names)
|
||||
let clipDescriptions = {}; // filename → description
|
||||
let customGroups = {}; // filename → groupId (from /groups)
|
||||
@@ -2510,6 +2527,7 @@
|
||||
}
|
||||
if (!map.has(gid)) map.set(gid, []);
|
||||
map.get(gid).push(f);
|
||||
fileGroups[f.cleanName] = gid;
|
||||
}
|
||||
// Sort each group: by explicit sort_order first, then by filename length
|
||||
for (const files of map.values()) {
|
||||
@@ -2573,6 +2591,7 @@
|
||||
const data = groupData.get(gid);
|
||||
if (!data) return;
|
||||
if (lbCurrentGid !== gid) { // clear refs when switching groups
|
||||
_prevGid = lbCurrentGid;
|
||||
_sbRefIndices = [];
|
||||
_sceneRefs = [null, null, null];
|
||||
_scenePersonInit = false;
|
||||
@@ -2580,6 +2599,8 @@
|
||||
stopOrbitFast();
|
||||
}
|
||||
lbCurrentGid = gid;
|
||||
_lastSelectedGid = gid;
|
||||
localStorage.setItem('lastSelectedGid', gid);
|
||||
lbUrls = data.urls;
|
||||
lbNames = data.names;
|
||||
lbIdx = startIdx !== undefined ? startIdx : (cycleIdx.get(gid) || 0);
|
||||
@@ -2613,6 +2634,60 @@
|
||||
openStudio(gid, idx);
|
||||
}
|
||||
|
||||
function jumpToPrevGroup() {
|
||||
if (_prevGid) openStudio(_prevGid);
|
||||
}
|
||||
|
||||
function formatPadValue(v) {
|
||||
if (v === undefined || v === null || v === '') return '0.00';
|
||||
let val = parseFloat(v);
|
||||
if (isNaN(val)) return '0.00';
|
||||
const s = v.toString();
|
||||
// User requested: show 0.00 if it contains a decimal see it as percentage.
|
||||
// if integer and its greater than 10 its pixel value
|
||||
if (s.includes('.') || s.includes('%')) return val.toFixed(2);
|
||||
if (val > 10) return val.toString();
|
||||
return val.toFixed(2);
|
||||
}
|
||||
|
||||
function updatePadPreview() {
|
||||
const viewer = document.getElementById('studioViewer');
|
||||
if (!viewer) return;
|
||||
// Clean up existing preview overlays
|
||||
viewer.querySelectorAll('.pad-preview-overlay').forEach(el => el.remove());
|
||||
|
||||
const isManual = !!document.getElementById('padBar');
|
||||
const getV = (side) => {
|
||||
const el = document.getElementById(isManual ? 'pad' + side : 'sbPad' + side);
|
||||
return el ? el.value : '0';
|
||||
};
|
||||
|
||||
const sides = ['Left', 'Right'];
|
||||
sides.forEach(side => {
|
||||
const vStr = getV(side);
|
||||
if (!vStr || vStr === '0' || vStr === '0.00') return;
|
||||
|
||||
const val = parseFloat(vStr);
|
||||
if (isNaN(val) || val <= 0) return;
|
||||
|
||||
const isPercent = vStr.includes('%') || vStr.includes('.');
|
||||
const width = isPercent ? (val + '%') : (val + 'px');
|
||||
|
||||
const overlay = document.createElement('div');
|
||||
overlay.className = 'pad-preview-overlay';
|
||||
overlay.style.top = '0';
|
||||
overlay.style.bottom = '0';
|
||||
if (side === 'Left') {
|
||||
overlay.style.left = '0';
|
||||
overlay.style.width = width;
|
||||
} else {
|
||||
overlay.style.right = '0';
|
||||
overlay.style.width = width;
|
||||
}
|
||||
viewer.appendChild(overlay);
|
||||
});
|
||||
}
|
||||
|
||||
function closeStudio() {
|
||||
document.getElementById('studio').classList.remove('open');
|
||||
document.body.style.overflow = '';
|
||||
@@ -2749,6 +2824,9 @@
|
||||
lbImgEl.src = lbUrls[lbIdx];
|
||||
}
|
||||
|
||||
const backBtn = document.getElementById('lbBackBtn');
|
||||
if (backBtn) backBtn.style.display = _prevGid ? '' : 'none';
|
||||
|
||||
const groupNameInput = document.getElementById('lbGroupNameInput');
|
||||
groupNameInput.value = groupNames[lbCurrentGid] || '';
|
||||
|
||||
@@ -3853,10 +3931,13 @@
|
||||
const bar = document.createElement('div');
|
||||
bar.id = 'padBar';
|
||||
bar.style.cssText = 'position:absolute;top:0;left:0;right:0;display:flex;gap:8px;padding:8px;background:rgba(0,0,0,0.85);z-index:101;justify-content:flex-end;align-items:center;flex-wrap:wrap;';
|
||||
const numInput = (id, label) =>
|
||||
`<label style="display:flex;align-items:center;gap:3px;font-size:11px;color:#ccc">${label}<input type="text" id="${id}" value="0" style="width:52px;background:#111;border:1px solid #333;color:#ccc;border-radius:4px;padding:2px 4px;font-size:11px;text-align:right" placeholder="px or %"></label>`;
|
||||
const numInput = (id, label) => {
|
||||
const onInput = `updatePadPreview()`;
|
||||
const onBlur = `this.value = formatPadValue(this.value); updatePadPreview()`;
|
||||
return `<label style="display:flex;align-items:center;gap:3px;font-size:11px;color:#ccc">${label}<input type="text" id="${id}" value="0.00" oninput="${onInput}" onblur="${onBlur}" style="width:52px;background:#111;border:1px solid #333;color:#ccc;border-radius:4px;padding:2px 4px;font-size:11px;text-align:right" placeholder="px or %"></label>`;
|
||||
};
|
||||
bar.innerHTML =
|
||||
`<span style="flex:1;font-size:11px;color:#aaa">Pad canvas (px):</span>`
|
||||
`<span style="flex:1;font-size:11px;color:#aaa">Pad canvas (px or %):</span>`
|
||||
+ numInput('padTop','↑')
|
||||
+ numInput('padRight','→')
|
||||
+ numInput('padBottom','↓')
|
||||
@@ -3873,10 +3954,13 @@
|
||||
+ `<button class="sb-btn" onclick="cancelManualPad()">Cancel</button>`
|
||||
+ `<button class="sb-btn primary" id="padConfirmBtn" onclick="confirmManualPad()">Pad</button>`;
|
||||
viewer.appendChild(bar);
|
||||
updatePadPreview();
|
||||
}
|
||||
|
||||
function cancelManualPad() {
|
||||
document.getElementById('padBar')?.remove();
|
||||
// Clean up preview overlays
|
||||
document.querySelectorAll('.pad-preview-overlay').forEach(el => el.remove());
|
||||
}
|
||||
|
||||
async function confirmManualPad() {
|
||||
@@ -4880,7 +4964,7 @@
|
||||
: `<img src="${firstVisUrl}" alt="${label}" loading="${isRecent ? 'eager' : 'lazy'}" onerror="this.style.opacity='0.2'">`;
|
||||
|
||||
return `
|
||||
<div class="image-card ${isNew ? 'new' : ''}" data-group="${safeGid}" onclick="handleCardClick(this)">
|
||||
<div class="image-card ${isNew ? 'new' : ''} ${_lastSelectedGid === gid ? 'highlight-prev' : ''}" data-group="${safeGid}" onclick="handleCardClick(this)">
|
||||
<div class="image-actions">
|
||||
${!isVideoCard ? `<div class="action-btn" title="Remove Background for Group" onclick="removeBgGroup(this, event)">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -5435,6 +5519,11 @@
|
||||
if ((e.key === 'p' || e.key === 'P') && tag !== 'INPUT' && tag !== 'TEXTAREA') {
|
||||
togglePrivacyMode(); return;
|
||||
}
|
||||
if ((e.key === 'a' || e.key === 'A') && tag !== 'INPUT' && tag !== 'TEXTAREA') {
|
||||
if (document.getElementById('studio').classList.contains('open')) {
|
||||
startManualPad(); return;
|
||||
}
|
||||
}
|
||||
if ((e.key === 'g' || e.key === 'G') && tag !== 'INPUT' && tag !== 'TEXTAREA') {
|
||||
if (_activeSidebarTab === 'generate') {
|
||||
const btn = document.getElementById('sbGenBtn');
|
||||
@@ -5831,10 +5920,12 @@
|
||||
<span style="font-size:11px;color:#666" title="Expand canvas before generation — gives the model space to outpaint">Pad:</span>
|
||||
${['Top','Right','Bottom','Left'].map(side => {
|
||||
const val = side==='Top'?_sbPadTop:side==='Right'?_sbPadRight:side==='Bottom'?_sbPadBottom:_sbPadLeft;
|
||||
const onInput = `updateSbGenBtn(); updatePadPreview()`;
|
||||
const onBlur = `this.value = formatPadValue(this.value); ${onInput}`;
|
||||
return `<label style="display:flex;align-items:center;gap:2px;font-size:11px;color:#888">${side[0]}
|
||||
<input type="text" id="sbPad${side}" value="${val}" placeholder="px or %"
|
||||
style="width:48px;background:#111;border:1px solid #2a2a2a;color:#ccc;border-radius:4px;padding:2px 4px;font-size:11px;text-align:right"
|
||||
oninput="updateSbGenBtn()"></label>`;
|
||||
oninput="${onInput}" onblur="${onBlur}"></label>`;
|
||||
}).join('')}
|
||||
<label style="display:flex;align-items:center;gap:3px;font-size:11px;color:#888;cursor:pointer" title="Instruct the model to fill in the padded area">
|
||||
<input type="checkbox" id="sbPadOutpaint" ${(_sbPadOutpaint??false)?'checked':''} onchange="updateSbGenBtn()" style="cursor:pointer">Outpaint</label>
|
||||
@@ -6087,7 +6178,13 @@
|
||||
bar.innerHTML = overlay.map(a => {
|
||||
const pSafe = a.prompt.replace(/'/g, "\\'");
|
||||
return `<button onclick="submitSingleAngle('${pSafe}')" title="${escHtml(a.name)}">${a.icon}</button>`;
|
||||
}).join('');
|
||||
}).join('') + `
|
||||
<button onclick="startManualPad()" title="Pad canvas (Expand image)" style="color:#f59e0b">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin:auto;display:block">
|
||||
<path d="M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"/>
|
||||
<path d="M12 8v8m-4-4h8"/>
|
||||
</svg>
|
||||
</button>`;
|
||||
}
|
||||
|
||||
function updateSbGenBtn() {
|
||||
|
||||
Reference in New Issue
Block a user