mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 04:40:09 +00:00
Add direct file download links to completed requests
Embeds a signed JWT download token (30-day expiry) in the requests API response so users can download completed audiobook/ebook files directly from the UI or by sharing the URL to apps like BookPlayer — no session cookie required. - jwt.ts: add generateDownloadToken / verifyDownloadToken helpers - api/requests: append downloadUrl to completed requests with a filePath - api/requests/[id]/download: new token-authenticated streaming endpoint; serves single files directly or zips multi-file audiobooks with adm-zip - RequestCard: add Download link in the actions area for completed requests
This commit is contained in:
@@ -26,12 +26,15 @@ interface RequestCardProps {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
completedAt?: string;
|
||||
downloadUrl?: string | null;
|
||||
audiobook: {
|
||||
id: string;
|
||||
audibleAsin?: string;
|
||||
title: string;
|
||||
author: string;
|
||||
coverArtUrl?: string;
|
||||
filePath?: string | null;
|
||||
fileFormat?: string | null;
|
||||
};
|
||||
};
|
||||
showActions?: boolean;
|
||||
@@ -49,6 +52,7 @@ export function RequestCard({ request, showActions = true }: RequestCardProps) {
|
||||
const requestType = request.type || 'audiobook';
|
||||
const isEbook = requestType === 'ebook';
|
||||
|
||||
const isCompleted = ['available', 'downloaded'].includes(request.status);
|
||||
const canCancel = ['pending', 'searching', 'downloading'].includes(request.status);
|
||||
const isActive = ['searching', 'downloading', 'processing'].includes(request.status);
|
||||
const isFailed = request.status === 'failed';
|
||||
@@ -271,6 +275,18 @@ export function RequestCard({ request, showActions = true }: RequestCardProps) {
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{isCompleted && request.downloadUrl && (
|
||||
<a
|
||||
href={request.downloadUrl}
|
||||
className="inline-flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 hover:underline"
|
||||
>
|
||||
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
Download
|
||||
</a>
|
||||
)}
|
||||
{canCancel && (
|
||||
<Button
|
||||
onClick={handleCancel}
|
||||
|
||||
Reference in New Issue
Block a user