diff --git a/configuration/homeScreen-configuration.js b/configuration/homeScreen-configuration.js
index 58fb855..fa0478e 100644
--- a/configuration/homeScreen-configuration.js
+++ b/configuration/homeScreen-configuration.js
@@ -3212,9 +3212,10 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
const editCtxBase = {
sectionType,
config: currentConfig,
- onSave: async (sectionData) => {
+ onSave: async (sectionData, saveOptions = {}) => {
const targetGroupName = sectionData._targetGroupName;
delete sectionData._targetGroupName;
+ const quiet = saveOptions?.quiet === true;
const found = findSectionInAllGroups(currentConfig, sectionData.id);
const savingToCustom = !found || found.groupType === 'CUSTOM_SECTION_GROUPS'
@@ -3239,7 +3240,7 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
found.group.sections.splice(found.sectionIndex, 1);
addSectionToGroup(currentConfig[found.groupType], targetGroupName, sectionData);
await saveConfig(currentConfig);
- showToast('Section saved');
+ if (!quiet) showToast('Section saved');
refreshMainModal({
focusSectionId: sectionData.id,
sectionType: sectionTypeForRow
@@ -3247,7 +3248,7 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
} else {
updateSectionInGroups(currentConfig[found.groupType], sectionData.id, sectionData);
await saveConfig(currentConfig);
- showToast('Section saved');
+ if (!quiet) showToast('Section saved');
if (updateSectionRowInPlace(sectionData, sectionTypeForRow)) {
scrollSectionRowIntoView(sectionData.id);
} else {
@@ -3260,7 +3261,7 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
} else {
addSectionToGroup(currentConfig.CUSTOM_SECTION_GROUPS, targetGroupName || 'Custom Sections', sectionData);
await saveConfig(currentConfig);
- showToast('Saved new Home Screen Section');
+ if (!quiet) showToast('Saved new Home Screen Section');
refreshMainModal({
focusSectionId: sectionData.id,
sectionType: 'custom'
@@ -5865,8 +5866,8 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
return { items: [], limit: 0, section: previewSection };
}
- const limit = withPreviewQueryOptions(queriesToLoad[0]).queryOptions.Limit
- || previewSection.itemLimit
+ const limit = previewSection.itemLimit
+ || withPreviewQueryOptions(queriesToLoad[0]).queryOptions.Limit
|| PREVIEW_DEFAULT_LIMIT;
allItems = window.cardBuilder.postProcessItems(previewSection, allItems);
const limitedItems = allItems.slice(0, parseInt(limit, 10));
diff --git a/configuration/homeScreenAdvancedEditor.js b/configuration/homeScreenAdvancedEditor.js
index a926d80..b167aa3 100644
--- a/configuration/homeScreenAdvancedEditor.js
+++ b/configuration/homeScreenAdvancedEditor.js
@@ -3925,10 +3925,13 @@
const state = modalInstance?._hsaeState;
if (!state || !importedSection) return;
const current = state.section || {};
- const context = state.context || {};
+ const context = { ...(state.context || {}) };
const merged = deepCloneJson(importedSection) || {};
merged.id = current.id || merged.id;
if (current.deleted === true) merged.deleted = true;
+ // Keep collect/export/troubleshoot bases in sync with the applied section
+ context.originalSection = deepCloneJson(merged);
+ context.section = merged;
const newState = buildEditorStateFromSection(merged, context);
modalInstance._hsaeState = newState;
const stateHost = modalInstance.dialogContainer || modalInstance.dialogContent;
@@ -4147,8 +4150,8 @@
const content = document.createElement('div');
content.innerHTML = `
- Restoring defaults will override the current editor values for this section with the KefinTweaks defaults.
- Enabled status and order are kept. You still need to Save to persist.
+ Restoring defaults will save the KefinTweaks defaults for this section and reload the editor.
+ Enabled status and order are kept.
${rowsHtml}
`;
@@ -4178,10 +4181,19 @@
modal.dialogFooter?.querySelector('#hsae-restore-cancel')?.addEventListener('click', () => {
window.ModalSystem.close(HSAE_RESTORE_DEFAULTS_MODAL_ID);
});
- modal.dialogFooter?.querySelector('#hsae-restore-proceed')?.addEventListener('click', () => {
+ modal.dialogFooter?.querySelector('#hsae-restore-proceed')?.addEventListener('click', async () => {
if (matching) return;
- window.ModalSystem.close(HSAE_RESTORE_DEFAULTS_MODAL_ID);
- if (typeof onProceed === 'function') onProceed();
+ const proceedBtn = modal.dialogFooter?.querySelector('#hsae-restore-proceed');
+ const cancelBtn = modal.dialogFooter?.querySelector('#hsae-restore-cancel');
+ if (proceedBtn) proceedBtn.disabled = true;
+ if (cancelBtn) cancelBtn.disabled = true;
+ try {
+ window.ModalSystem.close(HSAE_RESTORE_DEFAULTS_MODAL_ID);
+ if (typeof onProceed === 'function') await onProceed();
+ } catch (e) {
+ console.warn('[HSAE] Restore defaults failed:', e);
+ showHsaeToast('Failed to restore defaults');
+ }
});
}
});
@@ -4627,13 +4639,29 @@
const current = collectData(dialog, original) || deepCloneJson(state.section) || {};
if (state.section?.id) current.id = state.section.id;
const diffs = diffSectionAgainstDefault(current, canonical);
- showRestoreDefaultsConfirmModal(modalInstance, diffs, () => {
+ showRestoreDefaultsConfirmModal(modalInstance, diffs, async () => {
const merged = deepCloneJson(canonical) || {};
merged.id = current.id || sectionId;
if (Object.prototype.hasOwnProperty.call(current, 'enabled')) merged.enabled = current.enabled;
if (Object.prototype.hasOwnProperty.call(current, 'order')) merged.order = current.order;
if (current.deleted === true) merged.deleted = true;
- applyImportedSection(modalInstance, merged);
+
+ const callbacks = modalInstance._hsaeCallbacks || {};
+ const persist = typeof callbacks.persistSection === 'function'
+ ? callbacks.persistSection
+ : (typeof callbacks.onSave === 'function' ? callbacks.onSave : null);
+
+ if (persist) {
+ await persist(merged, { quiet: true });
+ if (typeof callbacks.remountAfterPersist === 'function') {
+ callbacks.remountAfterPersist(merged);
+ } else {
+ applyImportedSection(modalInstance, merged);
+ }
+ } else {
+ // No persist path (e.g. create flow): update editor only
+ applyImportedSection(modalInstance, merged);
+ }
showHsaeToast('Defaults restored');
});
}
@@ -4787,7 +4815,12 @@
modalInstance._hsaePreviewInitialized = false;
const section = context.section || {};
+ // Ensure collect/export/troubleshoot always have a stable original base
+ if (!context.originalSection) {
+ context = { ...context, originalSection: deepCloneJson(section) };
+ }
modalInstance._hsaeState = buildEditorStateFromSection(section, context);
+ modalInstance._hsaeCallbacks = callbacks || {};
const stateHost = modalInstance.dialogContainer || modalInstance.dialogContent;
if (stateHost) stateHost._hsaeState = modalInstance._hsaeState;
@@ -4808,10 +4841,11 @@
saveBtn.dataset.listenerAttached = 'true';
saveBtn.addEventListener('click', async () => {
const dialog = modalInstance.dialogContainer || modalInstance.dialogContent;
- const originalSection = context.originalSection || section;
+ const liveState = modalInstance._hsaeState;
+ const originalSection = liveState?.context?.originalSection || context.originalSection || section;
const sectionData = collectData(dialog, originalSection);
if (!sectionData) return;
- sectionData.id = section.id || originalSection.id;
+ sectionData.id = liveState?.section?.id || section.id || originalSection.id;
if (typeof updateSectionInConfig === 'function') {
updateSectionInConfig(sectionData);
}
diff --git a/configuration/homeScreenSectionEditor.js b/configuration/homeScreenSectionEditor.js
index 014c9c6..07a63bd 100644
--- a/configuration/homeScreenSectionEditor.js
+++ b/configuration/homeScreenSectionEditor.js
@@ -3299,6 +3299,56 @@
return null;
}
+ function buildAdvancedAttachContext(section, originalSection) {
+ const buildCtx = resolveAdvancedEditorBuildContext(section);
+ return {
+ section,
+ originalSection: originalSection || JSON.parse(JSON.stringify(section)),
+ ...buildCtx,
+ ...(activeEditCtx?.groupContext || {})
+ };
+ }
+
+ function buildAdvancedPersistCallbacks(modalInstance) {
+ return {
+ persistSection: async (sectionData, options = {}) => {
+ if (typeof activeEditCtx?.onSave !== 'function') {
+ throw new Error('No save handler available');
+ }
+ await activeEditCtx.onSave(sectionData, options);
+ },
+ remountAfterPersist: (sectionData) => {
+ remountOpenSectionEditor(modalInstance, sectionData);
+ }
+ };
+ }
+
+ function remountOpenSectionEditor(modalInstance, sectionData) {
+ if (!modalInstance?.dialogContent || !window.KefinHomeScreenAdvancedEditor) return;
+ const section = JSON.parse(JSON.stringify(sectionData || {}));
+ const originalSection = JSON.parse(JSON.stringify(section));
+ if (activeEditCtx) {
+ activeEditCtx.originalSection = originalSection;
+ }
+
+ window.KefinHomeScreenAdvancedEditor.destroyAppearancePickrs?.(modalInstance);
+ modalInstance.dialogContent.innerHTML = buildSectionEditorHTML(section);
+
+ const titleEl = modalInstance.dialogHeader?.querySelector('.dialogTitle, h2');
+ if (titleEl) {
+ // Keep the "Edit Section:" chrome; badge shows the live name
+ titleEl.textContent = `Edit Section: ${section.name || 'Unnamed'}`;
+ }
+
+ // Root listeners stay on dialogContent across innerHTML rebuilds — do not reset
+ // _hsaeRootListenersAttached or they will double-bind.
+ window.KefinHomeScreenAdvancedEditor.attachListeners(
+ modalInstance,
+ buildAdvancedAttachContext(section, originalSection),
+ buildAdvancedPersistCallbacks(modalInstance)
+ );
+ }
+
function openSectionEditorModal(section, ctx) {
const modalId = SECTION_EDITOR_MODAL_ID;
@@ -3308,6 +3358,8 @@
}
const originalSection = ctx.originalSection || JSON.parse(JSON.stringify(section));
+ if (ctx) ctx.originalSection = originalSection;
+ if (activeEditCtx) activeEditCtx.originalSection = originalSection;
const content = document.createElement('div');
content.innerHTML = buildSectionEditorHTML(section);
@@ -3343,33 +3395,22 @@
onOpen: (modalInstance) => {
if (modalInstance.dialogContent?.querySelector('.hsae-root') && window.KefinHomeScreenAdvancedEditor) {
window.KefinHomeScreenAdvancedEditor.setupModalHeader(modalInstance);
- let currentGroupName = activeEditCtx?.groupContext?.currentGroupName || '';
- if (!currentGroupName && section.id) {
- const config = getActiveConfig();
- let found = null;
- if (config) {
- const groupTypes = ['HOME_SECTION_GROUPS', 'SEASONAL_SECTION_GROUPS', 'DISCOVERY_SECTION_GROUPS', 'CUSTOM_SECTION_GROUPS'];
- for (const gt of groupTypes) {
- found = findSectionInGroupsForEditor(config[gt] || [], section.id);
- if (found) break;
- }
- }
- if (found) currentGroupName = found.group.name || '';
- }
- if (!currentGroupName && section._targetGroupName) currentGroupName = section._targetGroupName;
- const allGroups = getActiveConfig()?.CUSTOM_SECTION_GROUPS || [];
- const existingGroupNames = [...new Set(allGroups.map(g => g.name).filter(Boolean))];
- window.KefinHomeScreenAdvancedEditor.attachListeners(modalInstance, { section, ...(activeEditCtx?.groupContext || {}) });
+ window.KefinHomeScreenAdvancedEditor.attachListeners(
+ modalInstance,
+ buildAdvancedAttachContext(section, originalSection),
+ buildAdvancedPersistCallbacks(modalInstance)
+ );
}
// Attach event listeners
const saveSectionFromEditor = async () => {
- const sectionData = collectSectionEditorData(originalSection);
+ const liveOriginal = activeEditCtx?.originalSection || originalSection;
+ const sectionData = collectSectionEditorData(liveOriginal);
if (!sectionData) {
sectionEditorShowToast('Error collecting section data');
return null;
}
- sectionData.id = section.id;
+ sectionData.id = sectionData.id || liveOriginal?.id || section.id;
if (typeof ctx.onSave === 'function') {
await ctx.onSave(sectionData);
}
@@ -3438,12 +3479,13 @@
const previewBtn = modalInstance.dialogFooter.querySelector('.section-preview-btn');
if (previewBtn && typeof ctx.onPreview === 'function') {
previewBtn.addEventListener('click', async () => {
- const sectionData = collectSectionEditorData(originalSection);
+ const liveOriginal = activeEditCtx?.originalSection || originalSection;
+ const sectionData = collectSectionEditorData(liveOriginal);
if (!sectionData) {
sectionEditorShowToast('Error collecting section data for preview');
return;
}
- sectionData.id = sectionData.id || originalSection?.id || section.id;
+ sectionData.id = sectionData.id || liveOriginal?.id || section.id;
await ctx.onPreview(sectionData, ctx.sectionType, previewBtn);
});
}