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