download url

This commit is contained in:
2025-11-22 00:28:11 +01:00
parent dd7dae5f9d
commit c50372af06
6 changed files with 35 additions and 51 deletions
+8 -10
View File
@@ -40,7 +40,6 @@ interface UseDocumentPreviewArgs {
};
selectedFolder?: FolderId | null;
api: ApiClient;
resolveApiPath?: (path: string) => string;
notifyApiError: (error: unknown, message: string) => void;
navigate: NavigateHandler;
locationPathname: string;
@@ -67,7 +66,6 @@ const useDocumentPreview = ({
documentsManager,
selectedFolder,
api,
resolveApiPath,
notifyApiError,
navigate,
locationPathname,
@@ -109,7 +107,7 @@ const useDocumentPreview = ({
async (documentId: DocumentId, { force = false }: { force?: boolean } = {}): Promise<DocumentLink | null> => {
if (!documentId) return null;
const existing = documentLinks.get(documentId) || null;
const existing = documentLinks.get(documentId);
const now = Date.now();
const expiresAt = Number.isFinite(existing?.expiresAt) ? Number(existing?.expiresAt) : null;
if (!force && existing && (!expiresAt || expiresAt > now)) {
@@ -123,17 +121,17 @@ const useDocumentPreview = ({
const request: Promise<DocumentLink | null> = (async () => {
try {
const docResponse = await api.get<{ document?: Record<string, any> }>(`/documents/${documentId}`);
const downloadPath = docResponse.data?.document?.current_version?.download_path;
if (!downloadPath || !resolveApiPath) {
throw new Error('Document missing download path');
const download = docResponse.data?.document?.current_version?.download || null;
const downloadUrl = download?.url;
if (!downloadUrl) {
throw new Error('Document missing download url');
}
const href = resolveApiPath(downloadPath);
const entry: DocumentLink = {
url: href,
url: downloadUrl,
contentType: docResponse.data?.document?.current_version?.version?.content_type || null,
filename: docResponse.data?.document?.filename,
expiresAt: Date.now() + 5 * 60 * 1000,
expiresAt: download?.expires_at,
};
setDocumentLinks((prev) => {
const next = new Map(prev);
@@ -152,7 +150,7 @@ const useDocumentPreview = ({
previewInflightRef.current.set(documentId, request);
return request;
},
[documentLinks, api, resolveApiPath, notifyApiError],
[documentLinks, api, notifyApiError],
);
const ensurePreviewData = useCallback(
+18 -26
View File
@@ -8,7 +8,7 @@ export interface AssetObject {
ordinal?: number;
url?: string | null;
metadata?: Record<string, unknown> | null;
expires_at?: number | null;
expires_at?: number;
[key: string]: unknown;
}
@@ -16,10 +16,8 @@ export interface AssetLike {
id?: Identifier;
asset_type?: string;
cardinality?: number | null;
url?: string | null;
expires_at?: number | null;
download?: { url: string; expires_at: number } | null;
metadata?: Record<string, unknown> | null;
expiresAt?: number | null;
assets?: Record<string, AssetLike> | AssetLike[] | null;
objects?: AssetObject[] | null;
[key: string]: unknown;
@@ -37,19 +35,11 @@ export interface DocumentLike {
[key: string]: unknown;
}
export const resolveAssetExpiresAt = (
asset?: { expiresAt?: number | null; expires_at?: number | null } | null,
): number | null => {
const camel = Number(asset?.expiresAt);
if (Number.isFinite(camel)) {
return camel;
}
const snake = Number(asset?.expires_at);
if (Number.isFinite(snake)) {
return snake;
}
return null;
};
export const resolveAssetExpiresAt = (asset?: { download?: { expires_at: number } | null } | null): number | null =>
asset?.download?.expires_at ?? null;
export const resolveAssetUrl = (asset?: { download?: { url: string } | null } | null): string | null =>
asset?.download?.url ?? null;
export type EnsureAssetUrl = (
documentId: Identifier,
@@ -78,7 +68,7 @@ export const getAssetFromVersion = (currentVersion: Nullable<DocumentVersionLike
if (!currentVersion) {
return null;
}
return getAssetFromGroup(currentVersion.assets ?? null, assetType);
return getAssetFromGroup(currentVersion.assets, assetType);
};
const normalizeAssetObjects = (objects?: AssetObject[] | null): AssetObject[] => {
@@ -140,10 +130,11 @@ export class AssetView {
}
if (ordinal === 1 && this.asset) {
if (this.asset.url || this.asset.metadata) {
const primaryUrl = resolveAssetUrl(this.asset);
if (primaryUrl || this.asset.metadata) {
return {
ordinal: 1,
url: this.asset.url || null,
url: primaryUrl || null,
metadata: this.asset.metadata || null,
expires_at: resolveAssetExpiresAt(this.asset),
};
@@ -242,7 +233,7 @@ class AssetManager {
{ force = false }: { force?: boolean } = {},
): Promise<Nullable<AssetLike>> {
if (!documentId || !asset?.id) {
return Promise.resolve(asset ?? null);
return Promise.resolve(asset);
}
const baseAsset = this.assetCache.get(asset.id) || asset;
@@ -258,7 +249,8 @@ class AssetManager {
return true;
}
}
if (baseAsset.url && (!assetExpiresAt || assetExpiresAt > now)) {
const assetUrl = resolveAssetUrl(baseAsset);
if (assetUrl && (!assetExpiresAt || assetExpiresAt > now)) {
return true;
}
return false;
@@ -288,13 +280,13 @@ class AssetManager {
.then(({ data }) => {
const cachedEntry = this.assetCache.get(asset.id) || baseAsset;
const combined = { ...cachedEntry, ...asset, ...data };
const expiresAt =
const expires_at =
resolveAssetExpiresAt(data)
?? resolveAssetExpiresAt(combined)
?? Date.now() + this.assetPresignTtlMs;
?? resolveAssetExpiresAt(combined);
const entry = {
...combined,
expiresAt,
url: resolveAssetUrl(combined),
expires_at,
};
this.rememberAsset(entry);
+4 -4
View File
@@ -13,14 +13,14 @@ export type DocumentLike = OcrDocumentLike;
const asyncFalse = async () => false;
const resolveDocumentDownloadHref = (document?: DocumentLike | null, resolveApiPath?: ResolveApiPath | null): string | null => {
if (!document || !resolveApiPath) {
if (!document) {
return null;
}
const downloadPath = (document.current_version as { download_path?: string | null } | null)?.download_path;
if (!downloadPath) {
const downloadUrl = (document.current_version as { download?: { url: string } | null } | null)?.download?.url;
if (!downloadUrl) {
return null;
}
return resolveApiPath(downloadPath);
return resolveApiPath ? resolveApiPath(downloadUrl) : downloadUrl;
};
const hasDocumentOcrAsset = (document?: DocumentLike | null, getDocumentAsset?: GetDocumentAsset | null): boolean => {
@@ -450,7 +450,6 @@ const useDocumentsWorkspace = ({
documentsManager,
selectedFolder,
api,
resolveApiPath,
notifyApiError,
navigate,
locationPathname: location.pathname,
+4 -5
View File
@@ -38,7 +38,9 @@ interface DocumentLike {
correspondents?: Array<{ id?: string | number; name?: string }>;
current_version?: {
version_number?: number;
download?: { url?: string | null; expires_at?: number } | null;
version?: { content_type?: string | null } | null;
filename?: string | null;
} | null;
documentLink?: {
url: string;
@@ -261,11 +263,8 @@ const DocumentViewerPanel: React.FC<DocumentViewerPanelProps> = ({
if (!document) {
return null;
}
const downloadPath = document.current_version?.download_path;
if (!downloadPath) {
return null;
}
const href = resolveApiPath ? resolveApiPath(downloadPath) : downloadPath;
const downloadUrl = document.current_version?.download?.url;
const href = resolveApiPath ? resolveApiPath(downloadUrl) : downloadUrl;
if (!href) {
return null;
}
+1 -5
View File
@@ -6,12 +6,8 @@ import type {
GetAsset as AssetManagerGetAsset,
} from '../asset_manager';
interface DocumentVersion extends DocumentVersionLike {
download_path?: string | null;
}
export interface DocumentLike extends AssetManagerDocumentLike {
current_version?: DocumentVersion | null;
current_version?: DocumentVersionLike | null;
}
export type AssetLike = AssetManagerAssetLike;