mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-09-30 22:06:48 +01:00
Download history refactor pt.2 (#703)
Two-phase download history: downloads are now recorded in the DB at queue time (not just at terminal time), eliminating the need to reconstruct metadata in the terminal hook and removing the `_is_graduated_request_download()` request-scan mess
This commit is contained in:
@@ -299,16 +299,29 @@ function App() {
|
||||
}, [currentStatus, dismissedDownloadTaskIds]);
|
||||
|
||||
// Use real-time buckets for active work and merge persisted terminal buckets
|
||||
// so completed/errored entries survive restarts.
|
||||
const activitySidebarStatus = useMemo<StatusData>(() => ({
|
||||
// so completed/errored entries survive restarts. Filter out dismissed items
|
||||
// so the sidebar counts stay consistent with the activity panel.
|
||||
const activitySidebarStatus = useMemo<StatusData>(() => {
|
||||
const filterDismissed = (
|
||||
bucket: Record<string, Book> | undefined
|
||||
): Record<string, Book> | undefined => {
|
||||
if (!bucket || dismissedDownloadTaskIds.size === 0) return bucket;
|
||||
const filtered = Object.fromEntries(
|
||||
Object.entries(bucket).filter(([taskId]) => !dismissedDownloadTaskIds.has(taskId))
|
||||
) as Record<string, Book>;
|
||||
return Object.keys(filtered).length > 0 ? filtered : undefined;
|
||||
};
|
||||
|
||||
return {
|
||||
queued: currentStatus.queued,
|
||||
resolving: currentStatus.resolving,
|
||||
locating: currentStatus.locating,
|
||||
downloading: currentStatus.downloading,
|
||||
complete: mergeTerminalBucket(activityStatus.complete, currentStatus.complete),
|
||||
error: mergeTerminalBucket(activityStatus.error, currentStatus.error),
|
||||
cancelled: mergeTerminalBucket(activityStatus.cancelled, currentStatus.cancelled),
|
||||
}), [activityStatus, currentStatus]);
|
||||
complete: filterDismissed(mergeTerminalBucket(activityStatus.complete, currentStatus.complete)),
|
||||
error: filterDismissed(mergeTerminalBucket(activityStatus.error, currentStatus.error)),
|
||||
cancelled: filterDismissed(mergeTerminalBucket(activityStatus.cancelled, currentStatus.cancelled)),
|
||||
};
|
||||
}, [activityStatus, currentStatus, dismissedDownloadTaskIds]);
|
||||
|
||||
const showRequestsTab = useMemo(() => {
|
||||
if (requestRoleIsAdmin) {
|
||||
|
||||
@@ -175,6 +175,19 @@ const buildActions = (item: ActivityItem, isAdmin: boolean): ActivityCardAction[
|
||||
},
|
||||
];
|
||||
}
|
||||
if (item.visualStatus === 'cancelled') {
|
||||
return [
|
||||
{
|
||||
kind: 'download-retry',
|
||||
bookId: item.downloadBookId,
|
||||
},
|
||||
{
|
||||
kind: 'download-dismiss',
|
||||
bookId: item.downloadBookId,
|
||||
linkedRequestId: item.requestId,
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
kind: 'download-dismiss',
|
||||
|
||||
@@ -407,6 +407,7 @@ export const useActivity = ({
|
||||
void clearActivityHistory()
|
||||
.then(() => {
|
||||
void refreshActivitySnapshot();
|
||||
void refreshActivityHistory();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Clear history failed:', error);
|
||||
|
||||
@@ -430,7 +430,7 @@ export interface ActivityDismissPayload {
|
||||
}
|
||||
|
||||
export interface ActivityHistoryItem {
|
||||
id: number;
|
||||
id: string;
|
||||
user_id: number;
|
||||
item_type: 'download' | 'request';
|
||||
item_key: string;
|
||||
|
||||
@@ -207,7 +207,7 @@ export interface RequestRecord {
|
||||
id: number;
|
||||
user_id: number;
|
||||
status: 'pending' | 'fulfilled' | 'rejected' | 'cancelled';
|
||||
delivery_state?: 'none' | 'unknown' | 'queued' | 'resolving' | 'locating' | 'downloading' | 'complete' | 'error' | 'cancelled';
|
||||
delivery_state?: 'none' | 'queued' | 'resolving' | 'locating' | 'downloading' | 'complete' | 'error' | 'cancelled';
|
||||
delivery_updated_at?: string | null;
|
||||
last_failure_reason?: string | null;
|
||||
source_hint: string | null;
|
||||
|
||||
Reference in New Issue
Block a user