Compare commits
No commits in common. "22869df8a5fa85f781fb455a9bfeaebc86df4c5e" and "530fd03c22acf43cfe6616fd28f10c7372b8d629" have entirely different histories.
22869df8a5
...
530fd03c22
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "multi-hoster-uploader",
|
||||
"version": "3.0.8",
|
||||
"version": "3.0.7",
|
||||
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
@ -229,43 +229,18 @@ function _isHistoryTabActive() {
|
||||
const tab = document.querySelector('.tab.active');
|
||||
return !!(tab && tab.dataset.view === 'history');
|
||||
}
|
||||
// Cache the tab/view collections once and use event delegation on the parent
|
||||
// so tab switches don't trigger three querySelectorAll walks per click.
|
||||
(() => {
|
||||
const tabs = Array.from(document.querySelectorAll('.tab'));
|
||||
const views = Array.from(document.querySelectorAll('.view'));
|
||||
const tabsByView = {};
|
||||
const viewsById = {};
|
||||
for (const t of tabs) tabsByView[t.dataset.view] = t;
|
||||
for (const v of views) viewsById[v.id] = v;
|
||||
let activeTab = tabs.find(t => t.classList.contains('active')) || tabs[0];
|
||||
|
||||
const handle = (target) => {
|
||||
const tab = target.closest('.tab');
|
||||
if (!tab || tab === activeTab) return;
|
||||
if (activeTab) {
|
||||
activeTab.classList.remove('active');
|
||||
const prevView = viewsById[`${activeTab.dataset.view}-view`];
|
||||
if (prevView) prevView.classList.remove('active');
|
||||
}
|
||||
document.querySelectorAll('.tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
||||
document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
const nextView = viewsById[`${tab.dataset.view}-view`];
|
||||
if (nextView) nextView.classList.add('active');
|
||||
activeTab = tab;
|
||||
document.getElementById(`${tab.dataset.view}-view`).classList.add('active');
|
||||
if (tab.dataset.view === 'history') {
|
||||
_historyDirty = false;
|
||||
loadHistory();
|
||||
}
|
||||
};
|
||||
|
||||
const tabBar = tabs[0] && tabs[0].parentElement;
|
||||
if (tabBar) {
|
||||
tabBar.addEventListener('click', (e) => handle(e.target));
|
||||
} else {
|
||||
// Fallback: bind per-tab if somehow no common parent
|
||||
tabs.forEach(t => t.addEventListener('click', () => handle(t)));
|
||||
}
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
// --- Hoster selection ---
|
||||
function accountHasCreds(name, account) {
|
||||
@ -1200,22 +1175,6 @@ function handleRowClick(e, row) {
|
||||
// --- Context menu ---
|
||||
let alwaysOnTopState = false;
|
||||
|
||||
// Cache hoster-counts for the context menu. Invalidated on structural changes
|
||||
// to queueJobs (the length-based signature is good enough — a job's hoster
|
||||
// never changes after it's created).
|
||||
let _hosterCountsCache = { sig: '', result: new Map() };
|
||||
function _getHosterCounts() {
|
||||
const sig = `${queueJobs.length}`;
|
||||
if (_hosterCountsCache.sig === sig) return _hosterCountsCache.result;
|
||||
const m = new Map();
|
||||
for (let i = 0; i < queueJobs.length; i++) {
|
||||
const h = queueJobs[i].hoster;
|
||||
m.set(h, (m.get(h) || 0) + 1);
|
||||
}
|
||||
_hosterCountsCache = { sig, result: m };
|
||||
return m;
|
||||
}
|
||||
|
||||
function handleRowContextMenu(e, row) {
|
||||
e.preventDefault();
|
||||
const jobId = row.dataset.jobId;
|
||||
@ -1245,11 +1204,11 @@ function showContextMenu(x, y) {
|
||||
const startItem = menu.querySelector('[data-action="start-selected"]');
|
||||
if (startItem) startItem.textContent = n > 1 ? `Ausgewählte starten (${n})` : 'Ausgewählte starten';
|
||||
|
||||
// Dynamic "delete by hoster" submenu — cached count keyed by queue length
|
||||
// so a right-click on a 5000-job queue doesn't rescan everything.
|
||||
// Dynamic "delete by hoster" submenu
|
||||
const deleteHosterSubmenu = menu.querySelector('.ctx-hoster-delete-submenu');
|
||||
const deleteHosterContainer = menu.querySelector('.ctx-hoster-delete-items');
|
||||
const hosterCounts = _getHosterCounts();
|
||||
const hosterCounts = new Map();
|
||||
queueJobs.forEach(j => hosterCounts.set(j.hoster, (hosterCounts.get(j.hoster) || 0) + 1));
|
||||
deleteHosterContainer.innerHTML = '';
|
||||
if (hosterCounts.size > 0) {
|
||||
deleteHosterSubmenu.style.display = '';
|
||||
@ -2739,17 +2698,10 @@ async function saveSettings(options = {}) {
|
||||
newHosterSettings[name] = hs;
|
||||
}
|
||||
|
||||
// Fire both saves in parallel instead of serializing the two IPC round-trips.
|
||||
// Skip the getConfig refetch — we just wrote it, we know the new state, and
|
||||
// the round-trip added 100–200ms of UI stall per keystroke (autosave fires
|
||||
// on every input change).
|
||||
await Promise.all([
|
||||
window.api.saveHosterSettings(newHosterSettings),
|
||||
window.api.saveGlobalSettings(globalSettings)
|
||||
]);
|
||||
config.hosterSettings = newHosterSettings;
|
||||
config.globalSettings = globalSettings;
|
||||
hosterSettings = newHosterSettings;
|
||||
await window.api.saveHosterSettings(newHosterSettings);
|
||||
await window.api.saveGlobalSettings(globalSettings);
|
||||
config = await window.api.getConfig();
|
||||
hosterSettings = config.hosterSettings || {};
|
||||
clearTimeout(settingsSaveTimer);
|
||||
|
||||
// Start/stop folder monitor based on settings
|
||||
@ -3406,11 +3358,9 @@ function renderRecentUploadsPanel() {
|
||||
if (selectedRecentIds.has(id)) selectedRecentIds.delete(id);
|
||||
else selectedRecentIds.add(id);
|
||||
} else if (e.shiftKey && selectedRecentIds.size > 0) {
|
||||
// Reuse the already-sorted array from the sort cache instead of
|
||||
// querying every .recent-file-row in the DOM (O(visible) vs O(N)
|
||||
// on large panels).
|
||||
const sortedOrders = (_recentSortCache.result || sortRecentFiles(sessionFilesData))
|
||||
.map(r => r.order);
|
||||
// Use already-sorted DOM order (cheap) instead of re-sorting the full array.
|
||||
const sortedOrders = Array.from(tbody.querySelectorAll('.recent-file-row'))
|
||||
.map(r => parseInt(r.dataset.order, 10));
|
||||
const lastIdx = sortedOrders.findIndex(o => selectedRecentIds.has(o));
|
||||
const curIdx = sortedOrders.indexOf(id);
|
||||
if (lastIdx >= 0 && curIdx >= 0) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user