diff --git a/renderer/app.js b/renderer/app.js
index 620cb0b..195adb8 100644
--- a/renderer/app.js
+++ b/renderer/app.js
@@ -3485,12 +3485,15 @@ function renderAccounts() {
const runCheckBtn = document.getElementById('accountsRunHealthCheckBtn');
if (runCheckBtn) runCheckBtn.disabled = healthCheckRunning;
+ const footer = document.getElementById('accountsListFooter');
+
if (allAccounts.length === 0) {
container.innerHTML = `
Keine Accounts vorhanden
Klicke auf "Account hinzufügen", um einen Hoster einzurichten.
`;
+ if (footer) footer.style.display = 'none';
if (!_accountListenersBound) bindAccountListeners(container);
return;
}
@@ -3509,6 +3512,9 @@ function renderAccounts() {
}
container.innerHTML = html;
+ if (footer) footer.style.display = '';
+ _updateToggleAllAccountsBtn();
+
if (!_accountListenersBound) bindAccountListeners(container);
}
@@ -3578,6 +3584,35 @@ function _hosterLifetimeStat(name) {
}
function _invalidateHosterLifetimeCache() { _hosterLifetimeCache = null; }
+function _allAccountGroupsOpen() {
+ const bodies = document.querySelectorAll('#accountsList .account-hoster-group-body');
+ if (!bodies.length) return false;
+ for (const b of bodies) if (b.style.display === 'none') return false;
+ return true;
+}
+
+function _setAllAccountGroupsOpen(open) {
+ const groups = document.querySelectorAll('#accountsList .account-hoster-group');
+ groups.forEach(group => {
+ const name = group.dataset.hosterGroup;
+ const body = group.querySelector('.account-hoster-group-body');
+ const arrow = group.querySelector('.panel-arrow');
+ if (body) body.style.display = open ? '' : 'none';
+ if (arrow) arrow.innerHTML = open ? '▼' : '▶';
+ if (name) {
+ const summary = _summarizeHosterGroup(config.hosters[name] || []);
+ _hosterGroupOpenMemory.set(name, { state: open ? 'open' : 'closed', errorsAtClose: summary.error });
+ }
+ });
+ _updateToggleAllAccountsBtn();
+}
+
+function _updateToggleAllAccountsBtn() {
+ const btn = document.getElementById('toggleAllAccountsBtn');
+ if (!btn) return;
+ btn.textContent = _allAccountGroupsOpen() ? 'Alle einklappen' : 'Alle ausklappen';
+}
+
// Single set of delegated listeners on the accounts container. Bound once on
// the first render and reused for every subsequent in-place update / card
// swap. Previously we rebound 4 × N button listeners + 5 × N drag listeners
@@ -4484,6 +4519,7 @@ function setupListeners() {
document.getElementById('moveDownBtn').addEventListener('click', () => moveSelectedJobs('down'));
document.getElementById('moveBottomBtn').addEventListener('click', () => moveSelectedJobs('bottom'));
document.getElementById('accountsRunHealthCheckBtn').addEventListener('click', () => runHealthCheck('manual'));
+ document.getElementById('toggleAllAccountsBtn').addEventListener('click', () => _setAllAccountGroupsOpen(!_allAccountGroupsOpen()));
document.getElementById('copyAllLinksBtn').addEventListener('click', copyAllLinks);
document.getElementById('clearRecentFilesBtn').addEventListener('click', clearAllRecentFiles);
document.getElementById('exportRecentFilesBtn').addEventListener('click', exportAllRecentFiles);
diff --git a/renderer/index.html b/renderer/index.html
index 6495e54..baee95c 100644
--- a/renderer/index.html
+++ b/renderer/index.html
@@ -178,6 +178,9 @@
+
diff --git a/renderer/styles.css b/renderer/styles.css
index 2c0c16c..3b7ac44 100644
--- a/renderer/styles.css
+++ b/renderer/styles.css
@@ -793,6 +793,7 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; }
padding: 0 0 12px;
}
.accounts-list { display: grid; gap: 8px; }
+.accounts-list-footer { display: flex; justify-content: flex-end; margin-top: 12px; }
.account-card {
display: flex;