Files
bookhoard/web/src/queue.ts
T
john-okeefe f85c9c3f66 refactor(reader): Fix reader-context imports and remove dead code
Problem:
- Many format modules imported from '../core/reader-context'
- reader-context.ts was a local interface file, not a true context module
- Confusion between canonical reader-shell.ts and local reader-context.ts
- PDF page-cache.ts was 100% dead code (unused, unregistered, no exports)
- Several unused variables and imports across reader modules

Root Cause:
- reader-context.ts created as temporary file during refactoring
- Modules imported from it instead of canonical reader-shell.ts
- page-cache.ts copied from comic version but never integrated
- Incomplete refactoring left behind unused code

Solution:
- Update all imports to use reader-shell (canonical source)
- Remove unused page-cache.ts (dead code)
- Clean up unused variables and imports
- Consolidate type definitions

Changes:

Import Path Updates:
- comic/*: '../core/reader-context' → '../../reader-shell'
- manga/*: '../core/reader-context' → '../../reader-shell'
- pdf/*: '../core/reader-context' → '../../reader-shell'
- reflowable/ebook/*: '../core/reader-context' → '../../reader-shell'
- All now import UniversalReader from single source

Dead Code Removal:
- pdf/page-cache.ts: Deleted entirely
  - No init() function exported
  - Not registered in reader-shell.ts
  - All functions unused (createPDFPageCache, getCachedPage, etc.)
  - Only 2 lines of executable code (console.log, DOM cleanup)
  - 148 lines of dead code

Clean Up:
- navigator-panel.ts: Remove unused containerRect variable
- api-explorer-docs.ts, api.ts, queue.ts: Fix unused imports
- unlinked_books.ts: Remove unused variables
- panel-dock-system.ts: Remove unused context variables

Impact:
-  All modules use canonical type definitions
-  No more duplicate/conflicting interfaces
-  Dead code removed (148 lines)
-  Cleaner imports, easier maintenance
-  TypeScript compiler warnings resolved

Files changed: 26
Lines changed: +450, -520 (net -70 lines)
2026-04-10 23:21:44 -04:00

205 lines
5.7 KiB
TypeScript

import { Alpine } from "./alpine";
import { showToast } from "./toast";
async function refreshQueue(): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
try {
const response = await fetch("/api/queue/all", {
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
const data = await response.json();
renderQueueItems(data.items || []);
}
} catch (error) {
console.error("Failed to refresh queue:", error);
}
}
async function processPendingItems(): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
try {
const response = await fetch("/api/queue/process", {
method: "POST",
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
showToast("Processing queue items", "success");
refreshQueue();
}
} catch (error) {
console.error("Failed to process queue:", error);
showToast("Failed to process queue", "error");
}
}
async function clearFailedItems(): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
if (!confirm("Are you sure you want to clear all failed items?")) return;
try {
const response = await fetch("/api/queue/failed", {
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
showToast("Failed items cleared", "success");
refreshQueue();
}
} catch (error) {
console.error("Failed to clear failed items:", error);
showToast("Failed to clear items", "error");
}
}
async function clearAllItems(): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
if (!confirm("Are you sure you want to clear all queue items?")) return;
try {
const response = await fetch("/api/queue/all", {
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
showToast("Queue cleared", "success");
refreshQueue();
}
} catch (error) {
console.error("Failed to clear queue:", error);
showToast("Failed to clear queue", "error");
}
}
async function retryQueueItem(itemId: string): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
try {
const response = await fetch(`/api/queue/items/${itemId}/retry`, {
method: "POST",
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
showToast("Item queued for retry", "success");
refreshQueue();
}
} catch (error) {
console.error("Failed to retry item:", error);
showToast("Failed to retry item", "error");
}
}
async function deleteQueueItem(itemId: string): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
try {
const response = await fetch(`/api/queue/items/${itemId}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
});
if (response.ok) {
showToast("Item deleted", "success");
refreshQueue();
}
} catch (error) {
console.error("Failed to delete item:", error);
showToast("Failed to delete item", "error");
}
}
function renderQueueItems(items: QueueItemResponse[]): void {
const container = document.getElementById("queue-items");
if (!container) return;
if (items.length === 0) {
container.innerHTML =
'<p class="text-center p-4" style="color: var(--text-secondary)">Queue is empty</p>';
return;
}
container.innerHTML = items
.map(
(item) => `
<div class="p-3 rounded-lg border mb-2" style="background-color: var(--bg-secondary); border-color: var(--border)">
<div class="flex justify-between items-center">
<div>
<p class="font-medium" style="color: var(--text-primary)">${item.media_title || "Unknown"}</p>
<p class="text-sm" style="color: var(--text-secondary)">${item.status} - ${item.sync_type}</p>
<p class="text-xs" style="color: var(--text-secondary)">Attempts: ${item.attempts}/${item.max_attempts}</p>
</div>
<div class="flex space-x-2">
${item.status === "failed" ? `<button onclick="window.retryQueueItem('${item.id}')" class="btn-secondary px-2 py-1 rounded text-sm">Retry</button>` : ""}
<button onclick="window.deleteQueueItem('${item.id}')" class="btn-secondary px-2 py-1 rounded text-sm">Delete</button>
</div>
</div>
${item.error_message ? `<p class="text-xs mt-2" style="color: var(--accent)">${item.error_message}</p>` : ""}
</div>
`,
)
.join("");
}
function showQueueItemModal(): void {
const modal = document.getElementById("queue-item-modal");
const detailsContainer = document.getElementById("queue-item-details");
if (modal && detailsContainer) {
// TODO: Fetch and display item details
detailsContainer.innerHTML = "<p>Loading item details...</p>";
modal.classList.remove("hidden");
}
}
function hideQueueItemModal(): void {
const modal = document.getElementById("queue-item-modal");
if (modal) {
modal.classList.add("hidden");
}
}
function filterQueue(status: string): void {
const filterValue = status || "all";
// TODO: Implement filtering logic
console.log("Filter queue by:", filterValue);
}
export {
clearAllItems,
clearFailedItems,
deleteQueueItem,
processPendingItems,
refreshQueue,
retryQueueItem,
showQueueItemModal,
hideQueueItemModal,
filterQueue,
};
Alpine.data("queue", () => ({
clearAllItems,
clearFailedItems,
deleteQueueItem,
processPendingItems,
refreshQueue,
retryQueueItem,
showQueueItemModal,
hideQueueItemModal,
filterQueue,
}));