Eliminate tab reload animation after saving card properties
- CardSection._animateEntrance: skip after first render to prevent card fade-in replaying on every data refresh - automations: use reconcile() on subsequent renders instead of full innerHTML replacement that destroyed and recreated all cards - streams: same reconcile() approach for all 9 CardSections - targets/dashboard/streams: only show setTabRefreshing loading bar on first render when the tab is empty Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1092,7 +1092,7 @@ function _tplRenderSpectrum() {
|
||||
export async function loadPictureSources() {
|
||||
if (_sourcesLoading) return;
|
||||
set_sourcesLoading(true);
|
||||
setTabRefreshing('streams-list', true);
|
||||
if (!csRawStreams.isMounted()) setTabRefreshing('streams-list', true);
|
||||
try {
|
||||
const [streams] = await Promise.all([
|
||||
streamsCache.fetch(),
|
||||
@@ -1368,33 +1368,47 @@ function renderPictureSourcesList(streams) {
|
||||
});
|
||||
};
|
||||
|
||||
const panels = tabs.map(tab => {
|
||||
let panelContent = '';
|
||||
// Build item arrays for all sections
|
||||
const rawStreamItems = csRawStreams.applySortOrder(rawStreams.map(s => ({ key: s.id, html: renderStreamCard(s) })));
|
||||
const rawTemplateItems = csRawTemplates.applySortOrder(_cachedCaptureTemplates.map(t => ({ key: t.id, html: renderCaptureTemplateCard(t) })));
|
||||
const procStreamItems = csProcStreams.applySortOrder(processedStreams.map(s => ({ key: s.id, html: renderStreamCard(s) })));
|
||||
const procTemplateItems = csProcTemplates.applySortOrder(_cachedPPTemplates.map(t => ({ key: t.id, html: renderPPTemplateCard(t) })));
|
||||
const multiItems = csAudioMulti.applySortOrder(multichannelSources.map(s => ({ key: s.id, html: renderAudioSourceCard(s) })));
|
||||
const monoItems = csAudioMono.applySortOrder(monoSources.map(s => ({ key: s.id, html: renderAudioSourceCard(s) })));
|
||||
const audioTemplateItems = csAudioTemplates.applySortOrder(_cachedAudioTemplates.map(t => ({ key: t.id, html: renderAudioTemplateCard(t) })));
|
||||
const staticItems = csStaticStreams.applySortOrder(staticImageStreams.map(s => ({ key: s.id, html: renderStreamCard(s) })));
|
||||
const valueItems = csValueSources.applySortOrder(_cachedValueSources.map(s => ({ key: s.id, html: createValueSourceCard(s) })));
|
||||
|
||||
if (tab.key === 'raw') {
|
||||
panelContent =
|
||||
csRawStreams.render(csRawStreams.applySortOrder(rawStreams.map(s => ({ key: s.id, html: renderStreamCard(s) })))) +
|
||||
csRawTemplates.render(csRawTemplates.applySortOrder(_cachedCaptureTemplates.map(t => ({ key: t.id, html: renderCaptureTemplateCard(t) }))));
|
||||
} else if (tab.key === 'processed') {
|
||||
panelContent =
|
||||
csProcStreams.render(csProcStreams.applySortOrder(processedStreams.map(s => ({ key: s.id, html: renderStreamCard(s) })))) +
|
||||
csProcTemplates.render(csProcTemplates.applySortOrder(_cachedPPTemplates.map(t => ({ key: t.id, html: renderPPTemplateCard(t) }))));
|
||||
} else if (tab.key === 'audio') {
|
||||
panelContent =
|
||||
csAudioMulti.render(csAudioMulti.applySortOrder(multichannelSources.map(s => ({ key: s.id, html: renderAudioSourceCard(s) })))) +
|
||||
csAudioMono.render(csAudioMono.applySortOrder(monoSources.map(s => ({ key: s.id, html: renderAudioSourceCard(s) })))) +
|
||||
csAudioTemplates.render(csAudioTemplates.applySortOrder(_cachedAudioTemplates.map(t => ({ key: t.id, html: renderAudioTemplateCard(t) }))));
|
||||
} else if (tab.key === 'value') {
|
||||
panelContent = csValueSources.render(csValueSources.applySortOrder(_cachedValueSources.map(s => ({ key: s.id, html: createValueSourceCard(s) }))));
|
||||
} else {
|
||||
panelContent = csStaticStreams.render(csStaticStreams.applySortOrder(staticImageStreams.map(s => ({ key: s.id, html: renderStreamCard(s) }))));
|
||||
}
|
||||
if (csRawStreams.isMounted()) {
|
||||
// Incremental update: reconcile cards in-place
|
||||
tabs.forEach(tab => {
|
||||
const btn = container.querySelector(`.stream-tab-btn[data-stream-tab="${tab.key}"] .stream-tab-count`);
|
||||
if (btn) btn.textContent = tab.count;
|
||||
});
|
||||
csRawStreams.reconcile(rawStreamItems);
|
||||
csRawTemplates.reconcile(rawTemplateItems);
|
||||
csProcStreams.reconcile(procStreamItems);
|
||||
csProcTemplates.reconcile(procTemplateItems);
|
||||
csAudioMulti.reconcile(multiItems);
|
||||
csAudioMono.reconcile(monoItems);
|
||||
csAudioTemplates.reconcile(audioTemplateItems);
|
||||
csStaticStreams.reconcile(staticItems);
|
||||
csValueSources.reconcile(valueItems);
|
||||
} else {
|
||||
// First render: build full HTML
|
||||
const panels = tabs.map(tab => {
|
||||
let panelContent = '';
|
||||
if (tab.key === 'raw') panelContent = csRawStreams.render(rawStreamItems) + csRawTemplates.render(rawTemplateItems);
|
||||
else if (tab.key === 'processed') panelContent = csProcStreams.render(procStreamItems) + csProcTemplates.render(procTemplateItems);
|
||||
else if (tab.key === 'audio') panelContent = csAudioMulti.render(multiItems) + csAudioMono.render(monoItems) + csAudioTemplates.render(audioTemplateItems);
|
||||
else if (tab.key === 'value') panelContent = csValueSources.render(valueItems);
|
||||
else panelContent = csStaticStreams.render(staticItems);
|
||||
return `<div class="stream-tab-panel${tab.key === activeTab ? ' active' : ''}" id="stream-tab-${tab.key}">${panelContent}</div>`;
|
||||
}).join('');
|
||||
|
||||
return `<div class="stream-tab-panel${tab.key === activeTab ? ' active' : ''}" id="stream-tab-${tab.key}">${panelContent}</div>`;
|
||||
}).join('');
|
||||
|
||||
container.innerHTML = tabBar + panels;
|
||||
CardSection.bindAll([csRawStreams, csRawTemplates, csProcStreams, csProcTemplates, csAudioMulti, csAudioMono, csAudioTemplates, csStaticStreams, csValueSources]);
|
||||
container.innerHTML = tabBar + panels;
|
||||
CardSection.bindAll([csRawStreams, csRawTemplates, csProcStreams, csProcTemplates, csAudioMulti, csAudioMono, csAudioTemplates, csStaticStreams, csValueSources]);
|
||||
}
|
||||
}
|
||||
|
||||
export function onStreamTypeChange() {
|
||||
|
||||
Reference in New Issue
Block a user