updates UI
This commit is contained in:
@@ -732,6 +732,26 @@
|
||||
box-shadow: 0 0 8px rgba(59,130,246,0.6);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.lb-var-thumb.is-new {
|
||||
outline: 2px solid #10b981 !important;
|
||||
box-shadow: 0 0 12px rgba(16,185,129,0.8) !important;
|
||||
z-index: 10;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
.lb-var-thumb.is-orbit::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 38px;
|
||||
height: 8px;
|
||||
border: 1px solid rgba(96, 165, 250, 0.6);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 0 6px rgba(96, 165, 250, 0.4);
|
||||
z-index: 1;
|
||||
}
|
||||
.lb-var-thumb-check {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
@@ -2353,13 +2373,76 @@
|
||||
|
||||
// --- HYDRATION_START ---
|
||||
const PRELOADED_IMAGES = [
|
||||
"20260630_021844_view_000_000deg.png",
|
||||
"20260630_031441_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031430_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031419_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031408_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031357_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031346_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031335_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031324_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031313_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031302_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031251_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031240_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031229_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031218_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031207_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031156_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031145_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031134_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031123_dup_20260621_032709_image.nobg.png",
|
||||
"20260628_134529_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031014_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_031004_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_030953_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_030942_dup_20260621_032709_image.nobg.png",
|
||||
"20260630_030836_image.png",
|
||||
"20260630_030824_image.png",
|
||||
"20260630_030813_image.png",
|
||||
"20260630_030802_image.png",
|
||||
"20260630_030750_image.png",
|
||||
"20260630_030739_image.png",
|
||||
"20260630_030728_image.png",
|
||||
"20260630_030717_image.png",
|
||||
"20260630_030705_image.png",
|
||||
"20260630_030654_image.png",
|
||||
"20260630_030643_image.png",
|
||||
"20260630_030632_image.png",
|
||||
"20260630_030622_image.png",
|
||||
"20260630_030611_image.png",
|
||||
"20260630_024238_image.nobg.png",
|
||||
"20260630_024227_image.nobg.png",
|
||||
"20260630_024217_image.nobg.png",
|
||||
"20260630_023627_view_000_000deg.png",
|
||||
"20260630_023616_view_000_000deg.png",
|
||||
"20260630_023605_view_000_000deg.png",
|
||||
"20260630_023542_view_000_000deg.png",
|
||||
"20260630_023519_view_000_000deg.png",
|
||||
"20260630_023508_view_000_000deg.png",
|
||||
"20260630_023457_view_000_000deg.png",
|
||||
"20260630_023445_view_000_000deg.png",
|
||||
"20260630_023434_view_000_000deg.png",
|
||||
"20260630_023423_view_000_000deg.png",
|
||||
"20260630_023411_view_000_000deg.png",
|
||||
"20260630_023359_view_000_000deg.png",
|
||||
"20260630_023348_view_000_000deg.png",
|
||||
"20260630_023325_view_000_000deg.png",
|
||||
"20260630_023314_view_000_000deg.png",
|
||||
"20260630_023303_view_000_000deg.png",
|
||||
"20260630_023252_view_000_000deg.png",
|
||||
"20260630_023241_view_000_000deg.png",
|
||||
"20260630_023230_view_000_000deg.png",
|
||||
"20260630_022941_image.nobg.png",
|
||||
"20260630_022941_image.png",
|
||||
"20260620_152017_image.png",
|
||||
"20260630_022002_view_000_000deg.png",
|
||||
"20260630_021951_view_000_000deg.png",
|
||||
"20260630_021940_view_000_000deg.png",
|
||||
"20260630_021929_view_000_000deg.png",
|
||||
"20260630_021906_view_000_000deg.png",
|
||||
"20260630_021855_view_000_000deg.png",
|
||||
"20260630_021844_view_000_000deg.png",
|
||||
"20260630_021833_view_000_000deg.png",
|
||||
"20260630_021821_view_000_000deg.png",
|
||||
"20260630_021810_view_000_000deg.png",
|
||||
@@ -2912,7 +2995,6 @@
|
||||
"_turntable/cg_74544975/views/20260628_140758_view_000_000deg.png",
|
||||
"up_3a05a2de_face.png",
|
||||
"up_aa1add4d_face.png",
|
||||
"20260628_134529_dup_20260621_032709_image.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_135858_dup_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.png",
|
||||
"cg_7ec17537_face.png",
|
||||
"20260628_134529_dup_20260621_032709_image.png",
|
||||
@@ -6705,7 +6787,6 @@
|
||||
"20260621_231051_image.png",
|
||||
"20260621_231005_image.png",
|
||||
"20260618_011539_20260617_133129_img_77.png",
|
||||
"20260620_152017_image.png",
|
||||
"20260618_013452_out4.png",
|
||||
"20260620_025959_out4.png",
|
||||
"20260621_212650_image.png",
|
||||
@@ -7685,6 +7766,7 @@
|
||||
let _sbGenJobPollTimer= null;
|
||||
let _followLatestGid = null; // set to gid after generation to auto-jump to newest image
|
||||
let _followLatestFilename = null;
|
||||
let _highlightFilename = null; // visual highlight for newly generated item
|
||||
let _slideshowActive = false;
|
||||
let _slideshowTimer = null;
|
||||
let _slideshowInterval= 4000;
|
||||
@@ -7827,6 +7909,16 @@
|
||||
}
|
||||
|
||||
function getRepresentativeLabel(n) {
|
||||
// Priority 1: Pose Name
|
||||
if (filePoses[n]) {
|
||||
return filePoses[n];
|
||||
}
|
||||
|
||||
// Priority 2: Custom Prompt Sign (prompt exists but no standard pose)
|
||||
if (filePrompts[n]) {
|
||||
return '✎ Custom';
|
||||
}
|
||||
|
||||
if (isOrbitFile(n)) {
|
||||
const m = n.match(/_(\d+)deg/i) || n.match(/(\d+)deg/i) || n.match(/view_(\d+)/i);
|
||||
if (m) {
|
||||
@@ -8984,6 +9076,10 @@
|
||||
const act = i === lbIdx ? ' active' : '';
|
||||
const isSel = _selectedFilenames.has(n);
|
||||
const selCls = isSel ? ' selected' : '';
|
||||
const isOrb = isOrbitFile(n);
|
||||
const orbCls = isOrb ? ' is-orbit' : '';
|
||||
const isNew = n === _highlightFilename;
|
||||
const newCls = isNew ? ' is-new' : '';
|
||||
// Badge: Generate uses _sbRefIndices order; Scenery uses positional slots.
|
||||
const badge = _filmstripRefBadge(i);
|
||||
const refCls = badge > 0 ? ' ref-selected' : '';
|
||||
@@ -8993,7 +9089,7 @@
|
||||
? ' draggable="true" ondragstart="sceneFilmDragStart(event,' + i + ')"'
|
||||
: ' draggable="true" ondragstart="filmstripThumbDragStart(event,\'' + n.replace(/'/g, "\\'") + '\')"';
|
||||
const titleStr = _multiSelectModeActive ? 'Click to select' : 'Click to view · Shift+Click to add as ref';
|
||||
return '<div class="lb-var-thumb' + act + refCls + selCls + '" onclick="sbFilmstripClick(event,' + i + ')"' + dragAttr + ' title="' + titleStr + '">'
|
||||
return '<div class="lb-var-thumb' + act + refCls + selCls + orbCls + newCls + '" onclick="sbFilmstripClick(event,' + i + ')"' + dragAttr + ' title="' + titleStr + '">'
|
||||
+ '<img src="' + thumbSrc + '" loading="lazy" onerror="this.style.opacity=\'0.3\'">'
|
||||
+ (isVideo(n) ? '<div class="lb-var-play">▶</div>' : '')
|
||||
+ (pose ? '<div class="lb-var-pose">' + escHtml(pose) + '</div>' : '')
|
||||
@@ -11440,21 +11536,6 @@
|
||||
const visibleIdx = names.map((n, i) => i).filter(i => !fileHidden[names[i]]);
|
||||
groupData.set(gid, { urls, names, visibleIdx });
|
||||
|
||||
// Auto-follow: if a generation just finished for this group, jump to the image
|
||||
if (_followLatestFilename && names.includes(_followLatestFilename) && _isStudioOpen() && lbCurrentGid === gid) {
|
||||
lbIdx = names.indexOf(_followLatestFilename);
|
||||
_followLatestFilename = null;
|
||||
_followLatestGid = null;
|
||||
lbUrls = urls;
|
||||
lbNames = names;
|
||||
updateStudio();
|
||||
} else if (!_followLatestFilename && _followLatestGid === gid && _isStudioOpen() && lbCurrentGid === gid && names.length > 0) {
|
||||
_followLatestGid = null;
|
||||
lbIdx = names.length - 1;
|
||||
lbUrls = urls;
|
||||
lbNames = names;
|
||||
updateStudio();
|
||||
}
|
||||
|
||||
const isNew = gf.some(f => newFileNames.has(f.cleanName));
|
||||
const isRecent = gIdx < 3;
|
||||
@@ -11563,20 +11644,87 @@
|
||||
fresh.urls = mergedUrls;
|
||||
fresh.visibleIdx = fresh.names.map((_, idx) => idx).filter(idx => !fileHidden[fresh.names[idx]]);
|
||||
|
||||
lbUrls = mergedUrls;
|
||||
lbNames = mergedNames;
|
||||
|
||||
const newIdx = lbNames.indexOf(curName);
|
||||
if (newIdx >= 0) {
|
||||
lbIdx = newIdx;
|
||||
} else if (lbIdx >= lbNames.length) {
|
||||
lbIdx = lbNames.length - 1;
|
||||
// Now, handle auto-follow logic inside the open studio and current group context!
|
||||
let targetFname = null;
|
||||
if (_followLatestFilename && mergedNames.includes(_followLatestFilename)) {
|
||||
targetFname = _followLatestFilename;
|
||||
_followLatestFilename = null;
|
||||
_followLatestGid = null;
|
||||
} else if (!_followLatestFilename && _followLatestGid === lbCurrentGid && mergedNames.length > 0) {
|
||||
targetFname = mergedNames[mergedNames.length - 1];
|
||||
_followLatestGid = null;
|
||||
}
|
||||
|
||||
if (targetFname) {
|
||||
_highlightFilename = targetFname;
|
||||
|
||||
// Find the appropriate tab for targetFname
|
||||
let targetTab = _activeFilmstripTab;
|
||||
const isVid = isVideo(targetFname) || fileContentType[targetFname] === 'video';
|
||||
const isOrb = isOrbitFile(targetFname);
|
||||
const isHidden = !!fileHidden[targetFname];
|
||||
const isSource = !!fileIsSource[targetFname];
|
||||
const isArchived = !!fileArchived[targetFname];
|
||||
|
||||
let isVisibleInCurrentTab = false;
|
||||
if (_activeFilmstripTab === 'group') {
|
||||
isVisibleInCurrentTab = !isArchived;
|
||||
} else if (_activeFilmstripTab === 'active') {
|
||||
isVisibleInCurrentTab = !isHidden && !isSource && !isArchived && !isVid && !isOrb;
|
||||
} else if (_activeFilmstripTab === 'video') {
|
||||
isVisibleInCurrentTab = isVid && !isArchived;
|
||||
} else if (_activeFilmstripTab === 'orbit') {
|
||||
isVisibleInCurrentTab = isOrb && !isArchived;
|
||||
} else if (_activeFilmstripTab === 'hidden') {
|
||||
isVisibleInCurrentTab = isHidden && !isArchived;
|
||||
} else if (_activeFilmstripTab === 'source') {
|
||||
isVisibleInCurrentTab = isSource && !isArchived;
|
||||
} else if (_activeFilmstripTab === 'archived') {
|
||||
isVisibleInCurrentTab = isArchived;
|
||||
}
|
||||
|
||||
if (!isVisibleInCurrentTab) {
|
||||
if (isArchived) targetTab = 'archived';
|
||||
else if (isVid) targetTab = 'video';
|
||||
else if (isOrb) targetTab = 'orbit';
|
||||
else if (isHidden) targetTab = 'hidden';
|
||||
else if (isSource) targetTab = 'source';
|
||||
else targetTab = 'active';
|
||||
}
|
||||
|
||||
// Switch to the correct tab. switchFilmstripTab will update lbNames/lbUrls, highlight tab UI, and call updateStudio().
|
||||
switchFilmstripTab(targetTab);
|
||||
|
||||
// Locate and select targetFname in the newly loaded tab list
|
||||
const targetIdx = lbNames.indexOf(targetFname);
|
||||
if (targetIdx !== -1) {
|
||||
lbIdx = targetIdx;
|
||||
} else {
|
||||
lbIdx = 0;
|
||||
}
|
||||
|
||||
updateStudio();
|
||||
|
||||
// Clear highlight after 10 seconds
|
||||
const hfn = _highlightFilename;
|
||||
setTimeout(() => { if (_highlightFilename === hfn) { _highlightFilename = null; updateStudio(); } }, 10000);
|
||||
} else {
|
||||
// Regular reload sync: update lbNames and lbUrls filtered by the currently active tab
|
||||
const activeImageToPreserve = curName;
|
||||
switchFilmstripTab(_activeFilmstripTab);
|
||||
|
||||
// Overwrite switchFilmstripTab's selection if the image is still in this tab, otherwise fallback is already done
|
||||
const preservedIdx = lbNames.indexOf(activeImageToPreserve);
|
||||
if (preservedIdx !== -1) {
|
||||
lbIdx = preservedIdx;
|
||||
}
|
||||
updateStudio();
|
||||
}
|
||||
|
||||
// Re-map multi-ref selections to new positions by filename
|
||||
_sbRefIndices = oldRefNames
|
||||
.map(n => lbNames.indexOf(n))
|
||||
.filter(i => i >= 0);
|
||||
updateStudio();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user