Skip to content

Commit 443894c

Browse files
committed
overlay: centralize proxy PDF URL helper and bump v0.1.10
1 parent f7d0877 commit 443894c

File tree

7 files changed

+59
-48
lines changed

7 files changed

+59
-48
lines changed

.env.portainer.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Portainer stack environment (example values). Copy to `.env.portainer` for Portainer UI deployment.
22

33
# GHCR images to deploy (choose tags built by CI) — default to a pinned release tag
4-
PDF_PROXY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/pdf-proxy:v0.1.9
5-
WEB_LIBRARY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/web-library:v0.1.9
4+
PDF_PROXY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/pdf-proxy:v0.1.10
5+
WEB_LIBRARY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/web-library:v0.1.10
66

77
# Host path for Zotero WebDAV data mounted into the proxy container
88
ZOTERO_ROOT_HOST_PATH=/volume1/Reference/zotero

.env.stage.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Staging/NAS environment configuration (example values). Copy to `.env.stage` on the staging host.
22

33
# GHCR images to deploy (choose tags built by CI) — default to a pinned release tag
4-
PDF_PROXY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/pdf-proxy:v0.1.9
5-
WEB_LIBRARY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/web-library:v0.1.9
4+
PDF_PROXY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/pdf-proxy:v0.1.10
5+
WEB_LIBRARY_IMAGE=ghcr.io/joonsoome/on-prem-zotero-webui/web-library:v0.1.10
66

77
# Host path for Zotero WebDAV data mounted into the proxy container
88
ZOTERO_ROOT_HOST_PATH=/volume1/Reference/zotero

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
**Self-hosted Zotero WebUI Opensource Library + WebDAV-based PDF viewer **Avoid storage fees, keep privacy, and still enjoy a full browser-based Zotero library.
44

55
## It is PoC
6-
It(v0.1.9) is still fully not properly works, please keep on watching to be ready for production.
6+
It(v0.1.10) is still fully not properly works, please keep on watching to be ready for production.
77

88
---
99

app/web-library-overlay/src/js/actions/attachments.js

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PDFWorker } from '../common/pdf-worker.js';
66
import { REQUEST_EXPORT_PDF, RECEIVE_EXPORT_PDF, ERROR_EXPORT_PDF } from '../constants/actions';
77
import { saveAs } from 'file-saver';
88
import { READER_CONTENT_TYPES } from '../constants/reader';
9+
import { getProxyPdfUrl } from '../common/proxy';
910

1011
const tryGetFirstLink = itemKey => {
1112
return async (dispatch, getState) => {
@@ -32,16 +33,16 @@ const tryGetAttachmentURL = attachmentItemKey => {
3233
return async (dispatch, getState) => {
3334
const state = getState();
3435
const item = get(state, ['libraries', state.current.libraryKey, 'items', attachmentItemKey], null);
35-
const proxyBase = state.config?.pdfProxyBaseUrl;
36+
const proxyUrl = getProxyPdfUrl(state, attachmentItemKey);
3637

37-
// If a proxy base URL is configured, bypass Storage/enclosure links and use the proxy.
38-
if (proxyBase) {
38+
// If a proxy URL is available, bypass Storage/enclosure links and use the proxy.
39+
if (proxyUrl) {
3940
// Debug: trace when proxy URL is requested.
4041
console.log('[proxy-debug] tryGetAttachmentURL using proxy', {
4142
attachmentItemKey,
4243
linkMode: item?.linkMode,
4344
contentType: item?.contentType,
44-
proxyBase,
45+
proxyUrl,
4546
});
4647
return dispatch(getAttachmentUrl(attachmentItemKey));
4748
}
@@ -119,29 +120,29 @@ const pickBestItemAction = itemKey => {
119120
const pickBestAttachmentItemAction = attachmentItemKey => {
120121
return async (dispatch, getState) => {
121122
const state = getState();
122-
const current = state.current;
123-
const item = get(state, ['libraries', state.current.libraryKey, 'items', attachmentItemKey], null);
124-
const proxyBase = state.config?.pdfProxyBaseUrl;
125-
126-
const isFile = item && item.linkMode && item.linkMode.startsWith('imported') && item[Symbol.for('links')].enclosure;
127-
const isLink = item && item.linkMode && item.linkMode === 'linked_url';
128-
129-
if (isFile) {
130-
if (Object.keys(READER_CONTENT_TYPES).includes(item.contentType)) {
131-
// If proxy is available, prefer proxy URL to force PDF fetch even when reader path is used.
132-
if (proxyBase) {
133-
console.log('[proxy-debug] pickBestAttachmentItemAction -> proxy open', {
134-
attachmentItemKey,
135-
linkMode: item.linkMode,
136-
contentType: item.contentType,
137-
proxyBase,
138-
});
139-
return openDelayedURL(dispatch(getAttachmentUrl(attachmentItemKey)));
140-
}
123+
const current = state.current;
124+
const item = get(state, ['libraries', state.current.libraryKey, 'items', attachmentItemKey], null);
125+
const proxyUrl = getProxyPdfUrl(state, attachmentItemKey);
141126

142-
const readerPath = makePath(state.config, {
143-
attachmentKey: null,
144-
collection: current.collectionKey,
127+
const isFile = item && item.linkMode && item.linkMode.startsWith('imported') && item[Symbol.for('links')].enclosure;
128+
const isLink = item && item.linkMode && item.linkMode === 'linked_url';
129+
130+
if (isFile) {
131+
if (Object.keys(READER_CONTENT_TYPES).includes(item.contentType)) {
132+
// If proxy URL is available, prefer it to force PDF fetch even when reader path is used.
133+
if (proxyUrl) {
134+
console.log('[proxy-debug] pickBestAttachmentItemAction -> proxy open', {
135+
attachmentItemKey,
136+
linkMode: item.linkMode,
137+
contentType: item.contentType,
138+
proxyUrl,
139+
});
140+
return openDelayedURL(dispatch(getAttachmentUrl(attachmentItemKey)));
141+
}
142+
143+
const readerPath = makePath(state.config, {
144+
attachmentKey: null,
145+
collection: current.collectionKey,
145146
items: [attachmentItemKey],
146147
library: current.libraryKey,
147148
noteKey: null,

app/web-library-overlay/src/js/actions/items-read.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getItemKeysPath } from '../common/state';
55
import { get, getAbortController, mapRelationsToItemKeys } from '../utils';
66
import columnProperties from '../constants/column-properties';
77
import { connectionIssues, requestTracker, requestWithBackoff } from '.';
8+
import { getProxyPdfUrl } from '../common/proxy';
89

910
const fetchItems = (
1011
type,
@@ -241,29 +242,25 @@ const getAttachmentUrl = (itemKey, forceFresh = false) => {
241242
const { libraryKey } = state.current;
242243

243244
// On-prem overlay hook:
244-
// If a pdfProxyBaseUrl is configured, bypass the Zotero API attachment URL
245-
// and instead point directly at the on-prem PDF proxy.
246-
const pdfProxyBaseUrl = state.config?.pdfProxyBaseUrl;
247-
if(pdfProxyBaseUrl) {
248-
const base = pdfProxyBaseUrl.replace(/\/$/, '');
249-
const url = `${base}/${itemKey}`;
250-
245+
// Use centralized helper to resolve proxy URL for PDFs when configured.
246+
const proxyUrl = getProxyPdfUrl(state, itemKey);
247+
if(proxyUrl) {
251248
console.log('[proxy-debug] getAttachmentUrl', {
252249
itemKey,
253-
pdfProxyBaseUrl,
254250
libraryKey,
255251
forceFresh,
252+
proxyUrl,
256253
});
257254

258255
dispatch({
259256
type: RECEIVE_ATTACHMENT_URL,
260257
libraryKey,
261258
itemKey,
262259
forceFresh,
263-
url,
260+
url: proxyUrl,
264261
});
265262

266-
return url;
263+
return proxyUrl;
267264
}
268265

269266
const attachmentURLdata = state.libraries[state.current.libraryKey]?.attachmentsUrl[itemKey];
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const getProxyPdfUrl = (state, attachmentKey) => {
2+
const base = state?.config?.pdfProxyBaseUrl;
3+
if (!base || !attachmentKey) {
4+
return null;
5+
}
6+
const items = state.libraries?.[state.current?.libraryKey]?.items ?? {};
7+
const item = items[attachmentKey];
8+
const contentType = item?.contentType;
9+
if (contentType !== 'application/pdf') {
10+
return null;
11+
}
12+
return `${base.replace(/\/$/, '')}/${attachmentKey}`;
13+
};
14+
15+
export { getProxyPdfUrl };
16+

app/web-library-overlay/src/js/component/item-details/attachments.jsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { getFileData } from '../../common/event';
2323
import { pluralize } from '../../common/format';
2424
import { Toolbar, ToolGroup } from '../ui/toolbars';
2525
import { makePath } from '../../common/navigation';
26+
import { getProxyPdfUrl } from '../../common/proxy';
2627
import { useItemsState } from '../../hooks';
2728

2829
const AttachmentIcon = memo(({ isActive, item, size }) => {
@@ -77,12 +78,11 @@ const AttachmentActions = memo(props => {
7778
const search = useSelector(state => state.current.search);
7879
const tags = useSelector(state => state.current.tags);
7980
const config = useSelector(state => state.config);
80-
const pdfProxyBaseUrl = config?.pdfProxyBaseUrl;
8181
const [isDropdownOpen, setDropdownOpen] = useState(false);
8282
const canReparent = !isReadOnly && !isTrash && !isMyPublications;
8383
const isReaderCompatible = Object.keys(READER_CONTENT_TYPES).includes(attachment.contentType);
8484
const isPDF = attachment.contentType === 'application/pdf';
85-
const proxyHref = pdfProxyBaseUrl ? `${pdfProxyBaseUrl.replace(/\/$/, '')}/${itemKey}` : null;
85+
const proxyHref = useSelector(state => getProxyPdfUrl(state, itemKey));
8686
const canDownload = (
8787
(proxyHref && isPDF) ||
8888
(attachment.linkMode.startsWith('imported') && attachment[Symbol.for('links')].enclosure)
@@ -294,7 +294,6 @@ const Attachment = memo(props => {
294294
);
295295

296296
const libraryKey = useSelector(state => state.current.libraryKey);
297-
const pdfProxyBaseUrl = useSelector(state => state.config?.pdfProxyBaseUrl);
298297
const attachmentKey = useSelector(state => state.current.attachmentKey);
299298
const isTouchOrSmall = useSelector(state => state.device.isTouchOrSmall);
300299

@@ -319,7 +318,7 @@ const Attachment = memo(props => {
319318
const isFile = attachment.linkMode.startsWith('imported') &&
320319
attachment[Symbol.for('links')].enclosure;
321320
const isLink = attachment.linkMode === 'linked_url';
322-
const hasLink = isFile || isLink || Boolean(pdfProxyBaseUrl);
321+
const hasLink = isFile || isLink || Boolean(useSelector(state => getProxyPdfUrl(state, attachment.key)));
323322

324323
const handleKeyDown = useCallback(ev => {
325324
if (ev.key === 'ArrowRight') {
@@ -358,14 +357,12 @@ const Attachment = memo(props => {
358357

359358
dragRef(ref);
360359

361-
const proxyHref = pdfProxyBaseUrl ? `${pdfProxyBaseUrl.replace(/\/$/, '')}/${attachment.key}` : null;
362-
363360
const handleDoubleClick = useCallback(ev => {
364361
ev.stopPropagation();
365362
ev.preventDefault();
366363
console.log('[proxy-debug] row double-click', {
367364
key: attachment.key,
368-
proxyHref,
365+
proxyHref: getProxyPdfUrl({ ...state }, attachment.key), // log helper result
369366
linkMode: attachment.linkMode,
370367
contentType: attachment.contentType,
371368
});

0 commit comments

Comments
 (0)