release: v2.0.6

Redesign the desktop workspace with task sidebars, live filters, clearer settings, and an accessible update dialog.

Harden encrypted backup imports, configuration persistence, history retention, queue snapshots, shutdown recovery, and update installation ordering.

Publish verified Windows artifacts and refreshed English documentation.
This commit is contained in:
Sucukdeluxe
2026-08-10 09:28:28 +02:00
commit 76a228fb7c
113 changed files with 36923 additions and 0 deletions
+622
View File
@@ -0,0 +1,622 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline';">
<meta name="theme-color" content="#0f0f0f">
<title>Multi-Hoster-Upload</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<svg class="icon-sprite" aria-hidden="true">
<symbol id="icon-upload" viewBox="0 0 24 24"><path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5M5 14v4.5A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5V14"/></symbol>
<symbol id="icon-accounts" viewBox="0 0 24 24"><path d="M16.5 20v-1.5a4 4 0 0 0-4-4h-5a4 4 0 0 0-4 4V20M10 10.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Zm6-1a3 3 0 0 0 0-5.8m2.5 10.9a4 4 0 0 1 2 3.4v2"/></symbol>
<symbol id="icon-settings" viewBox="0 0 24 24"><path d="M12 15.25A3.25 3.25 0 1 0 12 8.75a3.25 3.25 0 0 0 0 6.5Zm7.2-3.25c0-.5-.05-.98-.15-1.45l2.05-1.6-2-3.46-2.52 1a8.12 8.12 0 0 0-2.5-1.44L13.7 2.4h-4l-.38 2.65a8.12 8.12 0 0 0-2.5 1.44l-2.52-1-2 3.46 2.05 1.6a7.1 7.1 0 0 0 0 2.9l-2.05 1.6 2 3.46 2.52-1a8.12 8.12 0 0 0 2.5 1.44l.38 2.65h4l.38-2.65a8.12 8.12 0 0 0 2.5-1.44l2.52 1 2-3.46-2.05-1.6c.1-.47.15-.95.15-1.45Z"/></symbol>
<symbol id="icon-history" viewBox="0 0 24 24"><path d="M4.25 7.75A9 9 0 1 1 3 12m1.25-4.25H8m-3.75 0V4M12 7.5V12l3 2"/></symbol>
<symbol id="icon-menu" viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h16"/></symbol>
<symbol id="icon-sliders" viewBox="0 0 24 24"><path d="M4 7h10m4 0h2M4 17h2m4 0h10M14 4v6M10 14v6"/></symbol>
<symbol id="icon-help" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M9.8 9a2.3 2.3 0 1 1 3.6 1.9c-.9.6-1.4 1.1-1.4 2.1m0 3.5h.01"/></symbol>
<symbol id="icon-download" viewBox="0 0 24 24"><path d="M12 4v11m0 0 4-4m-4 4-4-4M5 19h14"/></symbol>
<symbol id="icon-files" viewBox="0 0 24 24"><path d="M7 3h7l4 4v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Zm7 0v5h4M9 12h6m-6 4h6"/></symbol>
<symbol id="icon-check" viewBox="0 0 24 24"><path d="m5 12 4 4L19 6"/></symbol>
<symbol id="icon-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></symbol>
<symbol id="icon-alert" viewBox="0 0 24 24"><path d="M12 3 2.8 20h18.4L12 3Zm0 6v5m0 3h.01"/></symbol>
<symbol id="icon-cloud" viewBox="0 0 24 24"><path d="M7.5 18H18a4 4 0 0 0 .5-7.97A6.5 6.5 0 0 0 6 8.5v.25A4.75 4.75 0 0 0 7.5 18Z"/></symbol>
<symbol id="icon-close" viewBox="0 0 24 24"><path d="m6 6 12 12M18 6 6 18"/></symbol>
</svg>
<header class="app-header">
<div class="header-cluster header-primary">
<div class="app-brand" aria-label="Multi-Hoster Upload">
<img src="../assets/app_icon.png" alt="" class="app-brand-icon" width="24" height="24">
<span class="app-brand-name">MULTI-HOSTER UPLOAD</span>
</div>
<span class="header-divider" aria-hidden="true"></span>
<nav class="tab-bar" role="tablist" aria-label="Hauptbereiche">
<button class="tab active" id="upload-tab" role="tab" aria-selected="true" aria-controls="upload-view" tabindex="0" data-view="upload" title="Upload">
<svg class="top-nav-icon" aria-hidden="true"><use href="#icon-upload"></use></svg>
<span class="top-nav-label">Upload</span>
</button>
<button class="tab" id="accounts-tab" role="tab" aria-selected="false" aria-controls="accounts-view" tabindex="-1" data-view="accounts" title="Accounts">
<svg class="top-nav-icon" aria-hidden="true"><use href="#icon-accounts"></use></svg>
<span class="top-nav-label">Accounts</span>
</button>
<button class="tab" id="settings-tab" role="tab" aria-selected="false" aria-controls="settings-view" tabindex="-1" data-view="settings" title="Einstellungen">
<svg class="top-nav-icon" aria-hidden="true"><use href="#icon-settings"></use></svg>
<span class="top-nav-label">Einstellungen</span>
</button>
<button class="tab" id="history-tab" role="tab" aria-selected="false" aria-controls="history-view" tabindex="-1" data-view="history" title="Verlauf">
<svg class="top-nav-icon" aria-hidden="true"><use href="#icon-history"></use></svg>
<span class="top-nav-label">Verlauf</span>
</button>
</nav>
</div>
<div class="header-spacer" aria-hidden="true"></div>
<div class="header-cluster header-utilities">
<button class="header-update-button" id="headerUpdateBtn" title="Nach Aktualisierungen suchen" aria-label="Nach Aktualisierungen suchen" data-tooltip="Nach Aktualisierungen suchen">
<svg class="header-action-icon" aria-hidden="true"><use href="#icon-download"></use></svg>
<span class="header-update-label">Update</span>
</button>
<span class="header-divider" aria-hidden="true"></span>
<nav class="menu-bar" id="menuBar" aria-label="Anwendungsmenüs">
<div class="menu-bar-item" data-menu="datei">
<button class="menu-bar-trigger" data-menu-trigger="datei" title="Datei" aria-label="Datei">
<svg class="header-action-icon" aria-hidden="true"><use href="#icon-menu"></use></svg>
<span class="menu-label">Datei</span>
</button>
<div class="menu-dropdown" data-menu-dropdown="datei" style="display:none">
<button class="menu-dropdown-item" data-menu-action="add-files"><span>Dateien hinzufügen</span></button>
<button class="menu-dropdown-item" data-menu-action="add-folder"><span>Ordner hinzufügen</span></button>
<div class="menu-separator"></div>
<div class="menu-submenu" data-submenu="sicherung">
<button class="menu-submenu-trigger">Sicherung</button>
<div class="menu-submenu-dropdown" style="display:none">
<button class="menu-dropdown-item" data-menu-action="backup-export"><span>Exportieren</span></button>
<button class="menu-dropdown-item" data-menu-action="backup-import"><span>Importieren</span></button>
<button class="menu-dropdown-item" data-menu-action="online-backup-create"><span>Online-Schlüssel erstellen</span></button>
<button class="menu-dropdown-item" data-menu-action="online-backup-restore"><span>Online-Schlüssel importieren</span></button>
</div>
</div>
<div class="menu-separator"></div>
<button class="menu-dropdown-item" data-menu-action="restart"><span>Neustart</span></button>
<button class="menu-dropdown-item" data-menu-action="quit"><span>Beenden</span></button>
</div>
</div>
<div class="menu-bar-item" data-menu="einstellungen">
<button class="menu-bar-trigger" data-menu-trigger="einstellungen" title="Schnelleinstellungen" aria-label="Schnelleinstellungen">
<svg class="header-action-icon" aria-hidden="true"><use href="#icon-sliders"></use></svg>
<span class="menu-label">Einstellungen</span>
</button>
<div class="menu-dropdown" data-menu-dropdown="einstellungen" style="display:none">
<button class="menu-dropdown-item" data-menu-action="open-settings"><span>Einstellungen öffnen</span></button>
<div class="menu-separator"></div>
<div class="menu-settings-grid" id="menuSettingsGrid">
<span>Max. parallele Uploads</span>
<span></span>
<div class="menu-spinner">
<input type="text" inputmode="numeric" id="menuParallelInput" name="parallelUploads" autocomplete="off" aria-label="Maximale parallele Uploads">
<div class="menu-spinner-arrows">
<button data-spin="parallel-up" aria-label="Parallele Uploads erhöhen">&#9650;</button>
<button data-spin="parallel-down" aria-label="Parallele Uploads verringern">&#9660;</button>
</div>
</div>
<span></span>
<span>Geschwindigkeitslimit</span>
<input type="checkbox" id="menuSpeedLimitCheck" aria-label="Geschwindigkeitslimit aktivieren">
<div class="menu-spinner" id="menuSpeedSpinner">
<input type="text" inputmode="decimal" id="menuSpeedInput" name="speedLimit" autocomplete="off" aria-label="Geschwindigkeitslimit in Megabyte pro Sekunde">
<div class="menu-spinner-arrows">
<button data-spin="speed-up" aria-label="Geschwindigkeitslimit erhöhen">&#9650;</button>
<button data-spin="speed-down" aria-label="Geschwindigkeitslimit verringern">&#9660;</button>
</div>
</div>
<span class="menu-speed-unit">MB/s</span>
</div>
</div>
</div>
<div class="menu-bar-item" data-menu="hilfe">
<button class="menu-bar-trigger" data-menu-trigger="hilfe" title="Hilfe und Support" aria-label="Hilfe und Support">
<svg class="header-action-icon" aria-hidden="true"><use href="#icon-help"></use></svg>
<span class="menu-label">Hilfe</span>
</button>
<div class="menu-dropdown" data-menu-dropdown="hilfe" style="display:none">
<button class="menu-dropdown-item" data-menu-action="open-log-folder"><span>Log-Ordner öffnen</span></button>
<button class="menu-dropdown-item" data-menu-action="support-bundle"><span>Diagnose-Paket exportieren</span></button>
<div class="menu-separator"></div>
<button class="menu-dropdown-item" data-menu-action="check-updates"><span>Suche Aktualisierungen</span></button>
</div>
</div>
</nav>
<div class="version-badge" title="Installierte Version">
<span class="version-monogram" aria-hidden="true">U</span>
<span class="version-label" id="versionLabel"></span>
</div>
</div>
</header>
<div id="updateBanner" class="update-overlay" style="display:none" aria-hidden="true">
<section class="update-dialog" role="dialog" aria-modal="true" aria-labelledby="updateDialogTitle" aria-describedby="updateMessage" tabindex="-1">
<button class="update-close-button" id="updateCloseBtn" aria-label="Schließen">
<svg aria-hidden="true"><use href="#icon-close"></use></svg>
</button>
<div class="update-dialog-icon" aria-hidden="true">
<svg><use href="#icon-download"></use></svg>
</div>
<div class="update-dialog-copy">
<h2 id="updateDialogTitle">Eine neue Version ist verfügbar</h2>
<p id="updateMessage"></p>
</div>
<div class="update-release-notes" id="updateReleaseNotes" hidden></div>
<div class="update-progress" aria-live="polite">
<div class="update-progress-track"><span id="updateProgressBar" role="progressbar" aria-label="Update-Fortschritt" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-valuetext="0%"></span></div>
<span id="updateProgressText"></span>
</div>
<div class="update-dialog-actions">
<button class="btn btn-secondary" id="dismissUpdateBtn">Später erinnern</button>
<button class="btn btn-primary" id="installUpdateBtn">Jetzt updaten</button>
</div>
</section>
</div>
<div id="upload-view" class="view active" role="tabpanel" aria-labelledby="upload-tab">
<aside class="view-sidebar" aria-label="Upload-Übersicht">
<div class="view-sidebar-header">
<span class="view-sidebar-kicker">Arbeitsbereich</span>
<h1 class="view-sidebar-title">Uploads</h1>
</div>
<nav class="view-sidebar-navigation" aria-label="Upload-Status">
<button class="view-sidebar-item active" data-upload-sidebar-target="all" aria-label="Alle Dateien anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-files"></use></svg>
<span class="view-sidebar-copy">Alle Dateien</span>
<span class="view-sidebar-badge" id="uploadSidebarAllCount">0</span>
</button>
<button class="view-sidebar-item" data-upload-sidebar-target="active" aria-label="Aktive Uploads anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-upload"></use></svg>
<span class="view-sidebar-copy">Aktiv</span>
<span class="view-sidebar-badge" id="uploadSidebarActiveCount">0</span>
</button>
<button class="view-sidebar-item" data-upload-sidebar-target="waiting" aria-label="Wartende Uploads anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-clock"></use></svg>
<span class="view-sidebar-copy">Warteschlange</span>
<span class="view-sidebar-badge" id="uploadSidebarWaitingCount">0</span>
</button>
<button class="view-sidebar-item" data-upload-sidebar-target="done" aria-label="Fertige Uploads anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-check"></use></svg>
<span class="view-sidebar-copy">Fertig</span>
<span class="view-sidebar-badge" id="uploadSidebarDoneCount">0</span>
</button>
<button class="view-sidebar-item" data-upload-sidebar-target="error" aria-label="Fehlgeschlagene Uploads anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-alert"></use></svg>
<span class="view-sidebar-copy">Fehler</span>
<span class="view-sidebar-badge" id="uploadSidebarErrorCount">0</span>
</button>
</nav>
<div class="view-sidebar-section">
<span class="view-sidebar-section-label">Verfügbarkeit</span>
<div class="view-sidebar-summary">
<span>Bereite Accounts</span>
<strong id="uploadSidebarAccountsCount">0</strong>
</div>
<div class="view-sidebar-summary view-sidebar-summary-block hoster-summary" id="hosterSummary">Keine Upload-Ziele ausgewählt</div>
</div>
<div class="view-sidebar-footnote">Dateien ablegen, Ziele wählen und Uploads zentral steuern.</div>
</aside>
<main class="view-main upload-main">
<div class="upload-toolbar">
<div class="toolbar-left">
<div class="page-heading">
<h2>Upload-Aufträge</h2>
<p>Dateien hinzufügen, Ziele auswählen und Fortschritt verfolgen</p>
</div>
</div>
<div class="toolbar-right">
<button class="btn btn-xs btn-primary" id="addFilesBtn">+ Dateien</button>
<button class="btn btn-xs btn-secondary" id="addFolderBtn">+ Ordner</button>
</div>
</div>
<div class="upload-workspace">
<div class="drop-zone" id="dropZone">
<div class="drop-icon" aria-hidden="true"><svg><use href="#icon-cloud"></use></svg></div>
<p>Dateien hierher ziehen oder klicken</p>
<span>Dateien und Ordner werden vor dem Upload geprüft.</span>
</div>
<div class="queue-shell" id="queueShell" style="display:none">
<div class="queue-command-bar" id="queueCommandBar">
<button class="toolbar-btn" id="startUploadBtn" title="Alle Uploads starten" aria-label="Alle Uploads starten" disabled>
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><path d="M4 2l10 6-10 6z" fill="#4caf50"/></svg>
</button>
<button class="toolbar-btn" id="startSelectedBtn" title="Ausgewählte Uploads starten" aria-label="Ausgewählte Uploads starten" disabled>
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><path d="M6 3l8 5-8 5z" fill="#4caf50"/><rect x="1" y="3" width="3" height="10" rx="0.5" fill="#4caf50"/></svg>
</button>
<button class="toolbar-btn" id="reuploadSelectedBtn" title="Ausgewählte Datei erneut hochladen" aria-label="Ausgewählte Datei erneut hochladen">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><path d="M8 1a7 7 0 0 0-5 2.1V1H2v4h4V4H3.7A5.5 5.5 0 1 1 2.5 8H1a7 7 0 1 0 7-7z" fill="#4caf50"/></svg>
</button>
<button class="toolbar-btn" id="abortSelectedBtn" title="Ausgewählten Upload abbrechen" aria-label="Ausgewählten Upload abbrechen">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><rect x="3" y="3" width="10" height="10" rx="1" fill="#e53935"/><path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/></svg>
</button>
<button class="toolbar-btn" id="finishStopBtn" title="Aktive Uploads beenden und stoppen" aria-label="Aktive Uploads beenden und stoppen">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><path d="M2 8l4 4 8-8" stroke="#4caf50" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/><rect x="11" y="9" width="5" height="5" rx="1" fill="#e53935"/></svg>
</button>
<button class="toolbar-btn toolbar-btn-danger" id="abortAllBtn" title="Alle Uploads abbrechen" aria-label="Alle Uploads abbrechen">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><rect x="1" y="1" width="14" height="14" rx="2" fill="#e53935"/><path d="M4.5 4.5l7 7M11.5 4.5l-7 7" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>
</button>
<span class="toolbar-sep"></span>
<button class="toolbar-btn" id="moveTopBtn" title="Ganz nach oben" aria-label="Ganz nach oben">
<svg width="16" height="16" viewBox="0 0 16 16"><rect x="4" y="1" width="8" height="2" rx="0.5" fill="#4caf50"/><path d="M8 5l-4 5h8z" fill="#4caf50"/><path d="M8 9l-4 5h8z" fill="#4caf50"/></svg>
</button>
<button class="toolbar-btn" id="moveUpBtn" title="Nach oben" aria-label="Nach oben">
<svg width="16" height="16" viewBox="0 0 16 16"><path d="M8 2l-5 6h10z" fill="#4caf50"/><rect x="6" y="8" width="4" height="6" rx="0.5" fill="#4caf50"/></svg>
</button>
<button class="toolbar-btn" id="moveDownBtn" title="Nach unten" aria-label="Nach unten">
<svg width="16" height="16" viewBox="0 0 16 16"><rect x="6" y="2" width="4" height="6" rx="0.5" fill="#4caf50"/><path d="M8 14l-5-6h10z" fill="#4caf50"/></svg>
</button>
<button class="toolbar-btn" id="moveBottomBtn" title="Ganz nach unten" aria-label="Ganz nach unten">
<svg width="16" height="16" viewBox="0 0 16 16"><path d="M8 7l-4-5h8z" fill="#4caf50"/><path d="M8 11l-4-5h8z" fill="#4caf50"/><rect x="4" y="13" width="8" height="2" rx="0.5" fill="#4caf50"/></svg>
</button>
</div>
<div class="queue-container" id="queueContainer">
<table class="queue-table" id="queueTable">
<thead>
<tr>
<th class="col-filename sortable" data-col="filename" data-sort="filename">Dateiname<span class="col-resizer"></span></th>
<th class="col-size sortable" data-col="size" data-sort="size">Hochgeladen / Größe<span class="col-resizer"></span></th>
<th class="col-host sortable" data-col="host" data-sort="host">Hoster<span class="col-resizer"></span></th>
<th class="col-status sortable" data-col="status" data-sort="status">Status<span class="col-resizer"></span></th>
<th class="col-elapsed" data-col="elapsed">Zeit<span class="col-resizer"></span></th>
<th class="col-remaining" data-col="remaining">Rest<span class="col-resizer"></span></th>
<th class="col-speed sortable" data-col="speed" data-sort="speed">Geschwindigkeit<span class="col-resizer"></span></th>
<th class="col-progress sortable" data-col="progress" data-sort="progress">Fortschritt</th>
</tr>
</thead>
<tbody id="queueBody"></tbody>
</table>
</div>
<div class="queue-actions" id="queueActions" style="display:none">
<button class="btn btn-xs btn-primary" id="copyAllLinksBtn">Alle Links kopieren</button>
<select class="hs-input" id="linkExportFormat" title="Ausgabe-Format der kopierten Links" style="max-width:none;width:auto;min-width:130px">
<option value="plain">Plaintext</option>
<option value="bbcode">BBCode</option>
<option value="markdown">Markdown</option>
<option value="html">HTML</option>
<option value="csv">CSV</option>
<option value="json">JSON</option>
</select>
<button class="btn btn-xs btn-secondary" id="retryFailedBtn" style="display:none">Fehlgeschlagene erneut</button>
<button class="btn btn-xs btn-secondary" id="importLogBtn" title="Log importieren — bereits hochgeladene aus Queue entfernen">Log importieren</button>
</div>
<div class="resize-handle" id="recentFilesResizer"></div>
<div class="recent-files-panel" id="recentFilesPanel">
<div class="recent-files-header">
<div class="recent-tabs">
<button class="recent-tab active" data-panel="filesTab">Dateien</button>
<button class="recent-tab" data-panel="statsTab">Statistik</button>
</div>
<span class="recent-files-hint" id="recentFilesHint">Zuletzt erzeugte Upload-Links</span>
<button class="btn btn-xs btn-secondary" id="exportRecentFilesBtn" title="Alle Zeilen als Datei exportieren (Zeit, Hoster, Link, Dateiname)">Exportieren</button>
<button class="btn btn-xs btn-danger" id="clearRecentFilesBtn" title="Alle Links aus diesem Panel entfernen">Alle entfernen</button>
</div>
<div class="recent-tab-body active" id="filesTab">
<div class="recent-files-table-wrap">
<table class="recent-files-table">
<thead id="recentFilesHead">
<tr>
<th class="col-date sortable" data-recent-sort="date">Datum<span class="sort-indicator"></span></th>
<th class="col-filename sortable" data-recent-sort="filename">Dateiname<span class="sort-indicator"></span></th>
<th class="col-host sortable" data-recent-sort="host">Hoster<span class="sort-indicator"></span></th>
<th class="col-link sortable" data-recent-sort="link">Link<span class="sort-indicator"></span></th>
</tr>
</thead>
<tbody id="recentFilesBody"></tbody>
</table>
</div>
</div>
<div class="recent-tab-body" id="statsTab">
<div class="stats-grid">
<div class="stats-col">
<h4>Dateien in der Warteschlange</h4>
<div class="stats-row"><span>Gesamt:</span><span id="statQueueTotal">0</span></div>
<div class="stats-row"><span>Fertig:</span><span id="statQueueDone">0</span></div>
<div class="stats-row"><span>Verbleibend:</span><span id="statQueueRemaining">0</span></div>
<div class="stats-row"><span>Läuft:</span><span id="statQueueInProgress">0</span></div>
<div class="stats-row"><span>Fehler:</span><span id="statQueueError">0</span></div>
</div>
<div class="stats-col">
<h4>Dateigröße in der Warteschlange</h4>
<div class="stats-row"><span>Gesamt:</span><span id="statSizeTotal">0 B</span></div>
<div class="stats-row"><span>Verbleibend:</span><span id="statSizeRemaining">0 B</span></div>
</div>
<div class="stats-col">
<h4>Sitzung</h4>
<div class="stats-row"><span>Upload-Geschwindigkeit:</span><span id="statSpeed">0 B/s</span></div>
<div class="stats-row"><span>Restzeit:</span><span id="statEta">--:--</span></div>
<div class="stats-row"><span>Laufzeit:</span><span id="statRunTime">00:00:00</span></div>
<div class="stats-row"><span>In diesem Lauf hochgeladen:</span><span id="statSessionBytes">0 B</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<div id="accounts-view" class="view" role="tabpanel" aria-labelledby="accounts-tab">
<aside class="view-sidebar" aria-label="Account-Übersicht">
<div class="view-sidebar-header">
<span class="view-sidebar-kicker">Zugänge</span>
<h1 class="view-sidebar-title">Accounts</h1>
</div>
<nav class="view-sidebar-navigation" aria-label="Account-Status">
<button class="view-sidebar-item active" data-accounts-sidebar-filter="all" aria-label="Alle Accounts anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-accounts"></use></svg>
<span class="view-sidebar-copy">Alle Accounts</span>
<span class="view-sidebar-badge" id="accountsSidebarAllCount">0</span>
</button>
<button class="view-sidebar-item" data-accounts-sidebar-filter="ready" aria-label="Bereite Accounts anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-check"></use></svg>
<span class="view-sidebar-copy">Bereit</span>
<span class="view-sidebar-badge" id="accountsSidebarReadyCount">0</span>
</button>
<button class="view-sidebar-item" data-accounts-sidebar-filter="warning" aria-label="Accounts mit Handlungsbedarf anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-clock"></use></svg>
<span class="view-sidebar-copy">Aktion nötig</span>
<span class="view-sidebar-badge" id="accountsSidebarWarningCount">0</span>
</button>
<button class="view-sidebar-item" data-accounts-sidebar-filter="error" aria-label="Fehlerhafte Accounts anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-alert"></use></svg>
<span class="view-sidebar-copy">Fehler</span>
<span class="view-sidebar-badge" id="accountsSidebarErrorCount">0</span>
</button>
</nav>
<div class="view-sidebar-section view-sidebar-hoster-section">
<span class="view-sidebar-section-label">Hoster</span>
<div class="view-sidebar-hosters" id="accountsSidebarHosters"></div>
</div>
<div class="view-sidebar-footnote">Zugänge prüfen, priorisieren und für Uploads bereitstellen.</div>
</aside>
<main class="accounts-container view-main accounts-main">
<div class="accounts-header">
<div>
<h2>Accounts</h2>
<p class="settings-hint">Hoster-Zugangsdaten verwalten und prüfen</p>
</div>
<div class="accounts-header-actions">
<button class="btn btn-secondary" id="accountsRunHealthCheckBtn">Accounts prüfen</button>
<label class="auto-check-label accounts-auto-check" title="Automatischer Check vor dem Upload">
<input type="checkbox" id="autoHealthCheckToggle" checked>
<span>Auto-Check vor Upload</span>
</label>
<button class="btn btn-primary" id="addAccountBtn">Account hinzufügen</button>
</div>
</div>
<div class="health-check-results account-health-results" id="healthCheckResults"></div>
<div class="accounts-list" id="accountsList"></div>
<div class="accounts-list-footer" id="accountsListFooter" style="display:none">
<button class="btn btn-secondary" id="toggleAllAccountsBtn">Alle ausklappen</button>
</div>
</main>
</div>
<div class="modal-overlay" id="accountModal" style="display:none">
<div class="modal-card" role="dialog" aria-modal="true" aria-labelledby="accountModalTitle" aria-describedby="accountModalSubtitle">
<div class="modal-header">
<div>
<h3 id="accountModalTitle">Account hinzufügen</h3>
<p id="accountModalSubtitle">Wähle einen Hoster und gib deine Zugangsdaten ein.</p>
</div>
<button class="icon-btn" id="closeAccountModalBtn" aria-label="Schließen">&times;</button>
</div>
<div class="modal-body">
<div class="settings-row" id="accountHosterRow">
<label for="accountHosterSelect">Hoster</label>
<select class="key-input" id="accountHosterSelect" name="hoster" autocomplete="off" style="max-width:300px"></select>
</div>
<div class="settings-row">
<label for="accField_label">Label (optional)</label>
<input type="text" class="key-input" id="accField_label" name="accountLabel" autocomplete="off" placeholder="z. B. Hauptaccount, Premium, Kunde XY" maxlength="60">
</div>
<div id="accountCredsFields"></div>
<div class="account-modal-status" id="accountModalStatus" role="status" aria-live="polite"></div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancelAccountModalBtn">Abbrechen</button>
<button class="btn btn-primary" id="saveAccountBtn">Prüfen und anlegen</button>
</div>
</div>
</div>
<div class="modal-overlay" id="jobLogModal" style="display:none">
<div class="modal-card" style="width:min(820px,96%);max-height:80vh;display:flex;flex-direction:column">
<div class="modal-header">
<div><h3 id="jobLogTitle">Upload-Log</h3></div>
<button class="icon-btn" id="closeJobLogBtn" aria-label="Schließen">&times;</button>
</div>
<div class="modal-body" style="flex:1 1 auto;overflow:auto">
<pre id="jobLogBody" style="white-space:pre-wrap;font-family:ui-monospace,Consolas,Menlo,monospace;font-size:12px;line-height:1.4;margin:0">Keine Einträge.</pre>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="copyJobLogBtn">In Zwischenablage</button>
<button class="btn btn-primary" id="closeJobLogBtn2">Schließen</button>
</div>
</div>
</div>
<div class="modal-overlay" id="deleteAccountModal" style="display:none">
<div class="modal-card" style="width:min(400px,100%)">
<div class="modal-header">
<div><h3>Account löschen?</h3></div>
<button class="icon-btn" id="closeDeleteModalBtn" aria-label="Schließen">&times;</button>
</div>
<div class="modal-body">
<p id="deleteAccountMessage">Account wirklich löschen?</p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancelDeleteBtn">Abbrechen</button>
<button class="btn btn-danger" id="confirmDeleteBtn">Löschen</button>
</div>
</div>
</div>
<div id="settings-view" class="view" role="tabpanel" aria-labelledby="settings-tab">
<div class="settings-container">
<div class="settings-header">
<div>
<h2>Einstellungen</h2>
<p class="settings-hint">Alle Optionen nach Aufgaben sortiert. Änderungen werden automatisch gespeichert.</p>
</div>
<div class="settings-save-row">
<button class="btn btn-secondary" id="saveSettingsBtn">Jetzt speichern</button>
</div>
</div>
<div class="settings-hosters" id="settingsHosters"></div>
</div>
</div>
<div id="history-view" class="view" role="tabpanel" aria-labelledby="history-tab">
<aside class="view-sidebar" aria-label="Verlaufsübersicht">
<div class="view-sidebar-header">
<span class="view-sidebar-kicker">Archiv</span>
<h1 class="view-sidebar-title">Verlauf</h1>
</div>
<nav class="view-sidebar-navigation" aria-label="Verlaufsstatus">
<button class="view-sidebar-item active" data-history-filter="all" aria-label="Gesamten Verlauf anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-history"></use></svg>
<span class="view-sidebar-copy">Alle Uploads</span>
<span class="view-sidebar-badge" id="historySidebarAllCount">0</span>
</button>
<button class="view-sidebar-item" data-history-filter="success" aria-label="Erfolgreiche Uploads anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-check"></use></svg>
<span class="view-sidebar-copy">Erfolgreich</span>
<span class="view-sidebar-badge" id="historySidebarSuccessCount">0</span>
</button>
<button class="view-sidebar-item" data-history-filter="error" aria-label="Fehlgeschlagene Uploads anzeigen">
<svg class="view-sidebar-icon" aria-hidden="true"><use href="#icon-alert"></use></svg>
<span class="view-sidebar-copy">Fehler</span>
<span class="view-sidebar-badge" id="historySidebarErrorCount">0</span>
</button>
</nav>
<div class="view-sidebar-section">
<span class="view-sidebar-section-label">Aufbewahrung</span>
<div class="view-sidebar-summary">
<span>Aktive Regel</span>
<strong id="historySidebarRetention">Alles behalten</strong>
</div>
</div>
<div class="view-sidebar-footnote">Links wiederfinden, kopieren oder als Datei exportieren.</div>
</aside>
<main class="history-container view-main history-main">
<div class="history-header">
<h2>Upload-Verlauf</h2>
<div class="history-header-actions">
<label for="historyRetentionSelect" class="history-retention-label">Aufbewahrung</label>
<select id="historyRetentionSelect" class="key-input history-retention-select">
<option value="all">Alles behalten</option>
<option value="7d">Letzte 7 Tage</option>
<option value="30d">Letzte 30 Tage</option>
<option value="90d">Letzte 90 Tage</option>
<option value="1000">Letzte 1000 Uploads</option>
<option value="100">Letzte 100 Uploads</option>
</select>
<button class="btn btn-secondary" id="exportHistoryBtn">Verlauf exportieren</button>
<button class="btn btn-secondary" id="clearHistoryBtn">Verlauf löschen</button>
</div>
</div>
<div id="historyCapNotice" class="history-cap-notice" style="display:none"></div>
<div id="historyContainer"></div>
</main>
</div>
<div class="context-menu" id="contextMenu" style="display:none">
<div class="ctx-item" data-action="start-selected">Ausgewählte starten</div>
<div class="ctx-item" data-action="retry-selected">Erneut versuchen</div>
<div class="ctx-item" data-action="show-log">Log anzeigen</div>
<div class="ctx-separator"></div>
<div class="ctx-item" data-action="copy-links">Links kopieren</div>
<div class="ctx-item" data-action="copy-all-links">Alle Links kopieren</div>
<div class="ctx-separator"></div>
<div class="ctx-item" data-action="delete-selected">Entfernen</div>
<div class="ctx-item" data-action="delete-all">Alle entfernen</div>
<div class="ctx-submenu ctx-hoster-delete-submenu" style="display:none">
<div class="ctx-item ctx-item-danger">Hoster entfernen &#9656;</div>
<div class="ctx-submenu-items ctx-hoster-delete-items"></div>
</div>
</div>
<div class="context-menu" id="recentContextMenu" style="display:none">
<div class="ctx-item" data-action="recent-copy-links">Links kopieren</div>
<div class="ctx-item" data-action="recent-delete">Entfernen</div>
</div>
<div class="statusbar" id="statusbar">
<span class="sb-state" id="sbState">Bereit</span>
<span class="sb-separator">|</span>
<span class="sb-speed" id="sbSpeed">0 kB/s</span>
<span class="sb-separator">|</span>
<span class="sb-total" id="sbTotal">0 B</span>
<span class="sb-separator">|</span>
<span class="sb-eta" id="sbEta">ETA --:--</span>
<span class="sb-separator">|</span>
<span class="sb-connections" id="sbConnections">Verbindungen 0</span>
<span class="sb-separator">|</span>
<span class="sb-queue-count" id="sbQueueCount">Gesamt 0</span>
<span class="sb-separator">|</span>
<span class="sb-remaining-count" id="sbRemainingCount">Verbleibend 0</span>
<span class="sb-separator">|</span>
<span class="sb-progress-count" id="sbInProgressCount">Läuft 0</span>
<span class="sb-separator">|</span>
<span class="sb-done-count" id="sbDoneCount">Fertig 0</span>
<span class="sb-separator">|</span>
<span class="sb-error-count" id="sbErrorCount">Fehler 0</span>
</div>
<div class="copy-toast" id="copyToast"></div>
<div class="shutdown-overlay" id="shutdownOverlay" style="display:none">
<div class="shutdown-box">
<p id="shutdownMessage">System wird heruntergefahren in <span id="shutdownSeconds">60</span>s...</p>
<button class="btn btn-danger" id="cancelShutdownBtn">Abbrechen</button>
</div>
</div>
<div class="modal-overlay" id="hosterModal" style="display:none">
<div class="modal-card">
<div class="modal-header">
<div>
<h3>Upload-Ziele auswählen</h3>
<p>Dateien wurden hinzugefügt. Wähle jetzt die Hoster für den Upload.</p>
</div>
<button class="icon-btn" id="closeHosterModalBtn" aria-label="Schließen">&times;</button>
</div>
<div class="modal-body">
<div class="modal-actions-inline">
<button class="btn btn-xs btn-secondary" id="selectAllHostersBtn">Alle</button>
<button class="btn btn-xs btn-secondary" id="clearHostersBtn">Keine</button>
</div>
<div class="hoster-modal-list" id="hosterModalList"></div>
<p class="modal-hint" id="hosterModalHint"></p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancelHosterModalBtn">Abbrechen</button>
<button class="btn btn-primary" id="confirmHosterModalBtn">Übernehmen</button>
</div>
</div>
</div>
<script src="../lib/queue-prune.js"></script>
<script src="../lib/queue-dedup.js"></script>
<script src="../lib/log-mode.js"></script>
<script src="../lib/stats.js"></script>
<script src="../lib/throttled-cache.js"></script>
<script src="../lib/coalesced-set.js"></script>
<script src="../lib/throttle-timer.js"></script>
<script src="../lib/serialized-runner.js"></script>
<script src="account-submit.js"></script>
<script src="account-status.js"></script>
<script src="app.js"></script>
</body>
</html>