From 907ca6a29eb2767e00e1025ec1cd25e417fcada7 Mon Sep 17 00:00:00 2001 From: Ulrich Wohlfeil Date: Tue, 14 Feb 2023 14:14:29 +0100 Subject: [PATCH 1/4] Add SaveAsHandler for custom save as behavior --- src/apis/index.js | 2 ++ src/apis/setSaveAsHandler.js | 26 +++++++++++++++++++ .../FileAttachmentPanel.js | 8 +++++- .../ReplyAttachmentList.js | 8 +++++- .../onFileAttachmentDataAvailable.js | 8 +++++- src/helpers/downloadPdf.js | 8 +++++- src/helpers/pageManipulationFunctions.js | 15 +++++++++-- src/helpers/saveAs.js | 13 ++++++++++ src/redux/actions/internalActions.js | 4 +++ 9 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 src/apis/setSaveAsHandler.js create mode 100644 src/helpers/saveAs.js diff --git a/src/apis/index.js b/src/apis/index.js index eb90dd03e..24e2513af 100644 --- a/src/apis/index.js +++ b/src/apis/index.js @@ -10,6 +10,7 @@ import Theme from 'constants/theme'; import RedactionSearchPatterns from 'constants/redactionSearchPatterns'; import { languageEnum } from 'constants/languages'; import addSearchListener from './addSearchListener'; +import setSaveAsHandler from './setSaveAsHandler'; import addSortStrategy from './addSortStrategy'; import annotationPopup from './annotationPopup'; import closeDocument from './closeDocument'; @@ -278,6 +279,7 @@ export default (store) => { Theme, RedactionSearchPatterns, addSearchListener, + setSaveAsHandler, addSortStrategy: addSortStrategy(store), annotationPopup: annotationPopup(store), closeDocument: closeDocument(store), diff --git a/src/apis/setSaveAsHandler.js b/src/apis/setSaveAsHandler.js new file mode 100644 index 000000000..b4172a667 --- /dev/null +++ b/src/apis/setSaveAsHandler.js @@ -0,0 +1,26 @@ +/** + * Set save as handler that will be triggered in case of a save action instead of the default method. + * @method UI.setSaveAsHandler + * @param {UI.saveAsHandler} saveAsHandler Callback function that will be triggered when download started + * @example +WebViewer(...) + .then(function(instance) { + function onDownload(data, filename) { + console.log(filename); + }; + + instance.UI.setSaveAsHandler(onDownload); + }); + */ +/** + * Callback that gets passed to {@link UI.setSaveAsHandler setSaveAsHandler}. + * @callback UI.saveAsHandler + * @param {Blob|File} data data + * @param {string} filename filename + */ + +import { setSaveAsHandler as saveAsHandlerHelper } from 'helpers/saveAs'; + +export default function setSaveAsHandler(handler) { + saveAsHandlerHelper(handler); +} diff --git a/src/components/FileAttachmentPanel/FileAttachmentPanel.js b/src/components/FileAttachmentPanel/FileAttachmentPanel.js index be7d1afbd..795f34869 100644 --- a/src/components/FileAttachmentPanel/FileAttachmentPanel.js +++ b/src/components/FileAttachmentPanel/FileAttachmentPanel.js @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { getFileAttachments } from 'helpers/getFileAttachments'; import { saveAs } from 'file-saver'; +import { getSaveAsHandler } from 'helpers/saveAs'; import Icon from 'components/Icon'; import core from 'core'; import './FileAttachmentPanel.scss'; @@ -53,7 +54,12 @@ const FileAttachmentPanel = () => { {fileAttachments.embeddedFiles.map((file, idx) => renderAttachment( file.filename, () => { - saveAs(file.blob, file.filename); + if (getSaveAsHandler() !== null) { + var handler = getSaveAsHandler(); + handler(file.blob, file.filename); + } else { + saveAs(file.blob, file.filename); + } }, `embeddedFile_${idx}`, ), diff --git a/src/components/ReplyAttachmentList/ReplyAttachmentList.js b/src/components/ReplyAttachmentList/ReplyAttachmentList.js index f98b529f7..deffc9615 100644 --- a/src/components/ReplyAttachmentList/ReplyAttachmentList.js +++ b/src/components/ReplyAttachmentList/ReplyAttachmentList.js @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import selectors from 'selectors'; import { saveAs } from 'file-saver'; +import { getSaveAsHandler } from 'helpers/saveAs'; import Button from 'components/Button'; import Icon from 'components/Icon'; import Tooltip from 'components/Tooltip'; @@ -67,7 +68,12 @@ const ReplyAttachmentList = ({ files, isEditing, fileDeleted }) => { e.stopPropagation(); const fileData = file.url ? file.url : await decompressFileContent(file); - saveAs(fileData, file.name); + if (getSaveAsHandler() !== null) { + var handler = getSaveAsHandler(); + handler(fileData, file.name); + } else { + saveAs(fileData, file.name); + } }; return ( diff --git a/src/event-listeners/onFileAttachmentDataAvailable.js b/src/event-listeners/onFileAttachmentDataAvailable.js index 188366f36..8e48c0156 100644 --- a/src/event-listeners/onFileAttachmentDataAvailable.js +++ b/src/event-listeners/onFileAttachmentDataAvailable.js @@ -1,6 +1,12 @@ import { saveAs } from 'file-saver'; +import { getSaveAsHandler } from 'helpers/saveAs'; export default () => (fileMeta) => { const { fileData, fileName } = fileMeta; - saveAs(fileData, fileName); + if (getSaveAsHandler() !== null) { + var handler = getSaveAsHandler(); + handler(fileData, fileName); + } else { + saveAs(fileData, fileName); + } }; diff --git a/src/helpers/downloadPdf.js b/src/helpers/downloadPdf.js index 2b0346946..be0cf1137 100644 --- a/src/helpers/downloadPdf.js +++ b/src/helpers/downloadPdf.js @@ -1,4 +1,5 @@ import { saveAs } from 'file-saver'; +import { getSaveAsHandler } from 'helpers/saveAs'; import core from 'core'; import { isIE } from 'helpers/device'; import fireEvent from 'helpers/fireEvent'; @@ -238,7 +239,12 @@ export default async (dispatch, options = {}, documentViewerKey = 1) => { } else { file = new File([arr], downloadName, { type: downloadType }); } - saveAs(file, downloadName); + if (getSaveAsHandler() !== null) { + var handler = getSaveAsHandler(); + handler(file, downloadName); + } else { + saveAs(file, downloadName); + } dispatch(actions.closeElement('loadingModal')); fireEvent(Events.FINISHED_SAVING_PDF); fireEvent(Events.FILE_DOWNLOADED); diff --git a/src/helpers/pageManipulationFunctions.js b/src/helpers/pageManipulationFunctions.js index d716796ab..d62b82e28 100644 --- a/src/helpers/pageManipulationFunctions.js +++ b/src/helpers/pageManipulationFunctions.js @@ -1,6 +1,7 @@ import extractPagesWithAnnotations from 'helpers/extractPagesWithAnnotations'; import core from 'core'; import { saveAs } from 'file-saver'; +import { getSaveAsHandler } from 'helpers/saveAs'; import actions from 'actions'; import i18next from 'i18next'; import { workerTypes } from 'constants/types'; @@ -78,12 +79,22 @@ const extractPages = (pageNumbers, dispatch) => { title, confirmBtnText, onConfirm: () => extractPagesWithAnnotations(pageNumbers).then((file) => { - saveAs(file, 'extractedDocument.pdf'); + if (getSaveAsHandler() !== null) { + var handler = getSaveAsHandler(); + handler(file, 'extractedDocument.pdf'); + } else { + saveAs(file, 'extractedDocument.pdf'); + } }), secondaryBtnText, onSecondary: () => { extractPagesWithAnnotations(pageNumbers).then((file) => { - saveAs(file, 'extractedDocument.pdf'); + if (getSaveAsHandler() !== null) { + var handler = getSaveAsHandler(); + handler(file, 'extractedDocument.pdf'); + } else { + saveAs(file, 'extractedDocument.pdf'); + } core.removePages(pageNumbers).then(() => { dispatch(actions.setSelectedPageThumbnails([])); }); diff --git a/src/helpers/saveAs.js b/src/helpers/saveAs.js new file mode 100644 index 000000000..61683aa16 --- /dev/null +++ b/src/helpers/saveAs.js @@ -0,0 +1,13 @@ +let saveAsHandler = null; + +export function setSaveAsHandler(handler) { + saveAsHandler = handler; +} + +export function clearSaveAsHandler() { + saveAsHandler = null; +} + +export function getSaveAsHandler() { + return saveAsHandler; +} \ No newline at end of file diff --git a/src/redux/actions/internalActions.js b/src/redux/actions/internalActions.js index 7db86b18d..3286e6411 100644 --- a/src/redux/actions/internalActions.js +++ b/src/redux/actions/internalActions.js @@ -493,6 +493,10 @@ export const removeSearchListener = (func) => ({ type: 'REMOVE_SEARCH_LISTENER', payload: { func }, }); +export const setSaveAsHandler = (func) => ({ + type: 'ADD_SAVE_AS_HANDLER', + payload: { func }, +}); export const setSearchValue = (value) => ({ type: 'SET_SEARCH_VALUE', payload: { value }, From 7c8244d61c0270a08f8486f763a1f337918fdd2d Mon Sep 17 00:00:00 2001 From: Ulrich Wohlfeil Date: Fri, 17 Feb 2023 12:07:44 +0100 Subject: [PATCH 2/4] Fix Translations --- i18n/translation-de.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/i18n/translation-de.json b/i18n/translation-de.json index 679d88ced..418e56f4a 100644 --- a/i18n/translation-de.json +++ b/i18n/translation-de.json @@ -72,7 +72,7 @@ "markAllRead": "Als Gelesen markieren", "insertPage": "Seite einfügen", "insertBlankPageAbove": "Leere Seite oben einfügen", - "insertBlankPageBelow": "Leere Seite unten einfügen page", + "insertBlankPageBelow": "Leere Seite unten einfügen", "pageManipulation": "Seitenmanipulation", "replace": "Ersetzen", "setDestination": "Festgelegtes Ziel", @@ -88,9 +88,9 @@ "redactPages": "Seiten schwärzen", "playAudio": "Audio abspielen", "pauseAudio": "Audiopause", - "selectAll": "Wählen Sie Alle", + "selectAll": "Alle auswählen", "unselect": "Auswahl aufheben", - "addMark": "Markus hinzufügen", + "addMark": "Markieren", "viewFile": "Datei ansehen", "multiReplyAnnotations": "Auf ausgewählte Anmerkungen antworten ({{count}})", "comparePages": "Seiten vergleichen", @@ -317,8 +317,8 @@ "toolbarGroup-Measure": "Messen", "toolbarGroup-Edit": "Bearbeiten", "toolbarGroup-EditText": "Text bearbeiten", - "toolbarGroup-FillAndSign": "Füllen und unterschreiben", - "toolbarGroup-Forms": "Formen", + "toolbarGroup-FillAndSign": "Formular", + "toolbarGroup-Forms": "Zeichnen", "toolbarGroup-Redact": "Schwärzen" }, "annotationColor": { @@ -584,7 +584,7 @@ "backgroundColor": "Hintergrundfarbe" }, "pageRedactModal": { - "addMark": "Markus hinzufügen", + "addMark": "Markieren", "pageSelection": "Seitenauswahl", "current": "Aktuelle Seite", "specify": "Seiten angeben", @@ -599,18 +599,18 @@ "settings": "Einstellungen", "general": "Allgemein", "keyboardShortcut": "Tastaturkürzel", - "advancedSetting": "Erweiterte Einstellung", + "advancedSetting": "Erweitert", "language": "Sprache", "theme": "Thema", - "darkMode": "Dunkler Modus", - "lightMode": "Lichtmodus", + "darkMode": "Dark-Mode", + "lightMode": "Light-Mode", "viewing": "Anzeigen", - "disableFadePageNavigationComponent": "Deaktivieren Sie die Seitennavigationskomponente ausblenden", + "disableFadePageNavigationComponent": "Seitennavigationskomponente nicht automatisch ausblenden", "disableFadePageNavigationComponentDesc": "Lassen Sie die Seitennavigationskomponente immer auf dem Bildschirm. Das Standardverhalten besteht darin, es nach einer bestimmten Zeit der Inaktivität auszublenden.", "disableNativeScrolling": "Natives Scrollen deaktivieren", "disableNativeScrollingDesc": "Deaktivieren Sie das native Scrollverhalten mobiler Geräte, wenn es zuvor aktiviert wurde. Beachten Sie, dass das native Scrollverhalten mobiler Geräte standardmäßig deaktiviert ist.", "annotations": "Anmerkungen", - "disableToolDefaultStyleUpdateFromAnnotationPopup": "Deaktivieren Sie die Aktualisierung des Werkzeug-Standardstils aus dem Anmerkungs-Popup", + "disableToolDefaultStyleUpdateFromAnnotationPopup": "Aktualisierung des Werkzeug-Standardstils aus dem Anmerkungs-Popup deaktivieren", "disableToolDefaultStyleUpdateFromAnnotationPopupDesc": "Deaktiviert die Synchronisierung von Anmerkungsstilaktualisierungen mit dem zugeordneten Werkzeug, das die Anmerkung erstellt hat. Wenn also der Stil einer Anmerkung geändert wird, werden die Standardstile des Werkzeugs nicht aktualisiert.", "notesPanel": "Notizenbereich", "disableNoteSubmissionWithEnter": "Deaktivieren Sie das Senden von Notizen mit der Eingabetaste", @@ -962,9 +962,9 @@ }, "redactionPanel": { "noMarkedRedactions": "Beginnen Sie mit dem Schwärzen, indem Sie Text, Regionen, Seiten markieren oder eine Suche durchführen.", - "redactionSearchPlaceholder": "Hinzufügen nach Schlüsselwortsuche oder Mustern", + "redactionSearchPlaceholder": "Schlüsselwortsuche oder Muster", "redactionCounter": "Zur Schwärzung markiert", - "clearMarked": "Klar", + "clearMarked": "Abbrechen", "redactAllMarked": "Alle schwärzen", "redactionItem": { "regionRedaction": "Regionsredaktion", From ee8f7075e8ca6007245577d98b9161439359e258 Mon Sep 17 00:00:00 2001 From: Ulrich Wohlfeil Date: Thu, 23 Feb 2023 19:37:40 +0100 Subject: [PATCH 3/4] Thumbnail multiselect checkbox scss fix --- src/components/Choice/Choice.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Choice/Choice.scss b/src/components/Choice/Choice.scss index 75cc6d9bd..43ec3b033 100644 --- a/src/components/Choice/Choice.scss +++ b/src/components/Choice/Choice.scss @@ -10,6 +10,10 @@ align-items: center; } +.ui__choice__input input { + position: unset !important; +} + .ui__choice__input--switch { .ui__choice__input__switch { height: 14px !important; From 4c2f870a75460ac9163afb7af89a624709f83412 Mon Sep 17 00:00:00 2001 From: Ulrich Wohlfeil Date: Wed, 1 Mar 2023 09:52:07 +0100 Subject: [PATCH 4/4] https://github.com/PDFTron/webviewer-ui/pull/1000#pullrequestreview-1318896398 --- src/components/Choice/Choice.scss | 4 ---- src/components/FileAttachmentPanel/FileAttachmentPanel.js | 2 +- src/components/ReplyAttachmentList/ReplyAttachmentList.js | 2 +- src/event-listeners/onFileAttachmentDataAvailable.js | 2 +- src/helpers/downloadPdf.js | 2 +- src/helpers/pageManipulationFunctions.js | 4 ++-- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/components/Choice/Choice.scss b/src/components/Choice/Choice.scss index 43ec3b033..75cc6d9bd 100644 --- a/src/components/Choice/Choice.scss +++ b/src/components/Choice/Choice.scss @@ -10,10 +10,6 @@ align-items: center; } -.ui__choice__input input { - position: unset !important; -} - .ui__choice__input--switch { .ui__choice__input__switch { height: 14px !important; diff --git a/src/components/FileAttachmentPanel/FileAttachmentPanel.js b/src/components/FileAttachmentPanel/FileAttachmentPanel.js index 795f34869..17f528d71 100644 --- a/src/components/FileAttachmentPanel/FileAttachmentPanel.js +++ b/src/components/FileAttachmentPanel/FileAttachmentPanel.js @@ -55,7 +55,7 @@ const FileAttachmentPanel = () => { file.filename, () => { if (getSaveAsHandler() !== null) { - var handler = getSaveAsHandler(); + const handler = getSaveAsHandler(); handler(file.blob, file.filename); } else { saveAs(file.blob, file.filename); diff --git a/src/components/ReplyAttachmentList/ReplyAttachmentList.js b/src/components/ReplyAttachmentList/ReplyAttachmentList.js index deffc9615..d3dc8c12d 100644 --- a/src/components/ReplyAttachmentList/ReplyAttachmentList.js +++ b/src/components/ReplyAttachmentList/ReplyAttachmentList.js @@ -69,7 +69,7 @@ const ReplyAttachmentList = ({ files, isEditing, fileDeleted }) => { const fileData = file.url ? file.url : await decompressFileContent(file); if (getSaveAsHandler() !== null) { - var handler = getSaveAsHandler(); + const handler = getSaveAsHandler(); handler(fileData, file.name); } else { saveAs(fileData, file.name); diff --git a/src/event-listeners/onFileAttachmentDataAvailable.js b/src/event-listeners/onFileAttachmentDataAvailable.js index 8e48c0156..373886e5f 100644 --- a/src/event-listeners/onFileAttachmentDataAvailable.js +++ b/src/event-listeners/onFileAttachmentDataAvailable.js @@ -4,7 +4,7 @@ import { getSaveAsHandler } from 'helpers/saveAs'; export default () => (fileMeta) => { const { fileData, fileName } = fileMeta; if (getSaveAsHandler() !== null) { - var handler = getSaveAsHandler(); + const handler = getSaveAsHandler(); handler(fileData, fileName); } else { saveAs(fileData, fileName); diff --git a/src/helpers/downloadPdf.js b/src/helpers/downloadPdf.js index be0cf1137..858c1419f 100644 --- a/src/helpers/downloadPdf.js +++ b/src/helpers/downloadPdf.js @@ -240,7 +240,7 @@ export default async (dispatch, options = {}, documentViewerKey = 1) => { file = new File([arr], downloadName, { type: downloadType }); } if (getSaveAsHandler() !== null) { - var handler = getSaveAsHandler(); + const handler = getSaveAsHandler(); handler(file, downloadName); } else { saveAs(file, downloadName); diff --git a/src/helpers/pageManipulationFunctions.js b/src/helpers/pageManipulationFunctions.js index d62b82e28..42fb5774c 100644 --- a/src/helpers/pageManipulationFunctions.js +++ b/src/helpers/pageManipulationFunctions.js @@ -80,7 +80,7 @@ const extractPages = (pageNumbers, dispatch) => { confirmBtnText, onConfirm: () => extractPagesWithAnnotations(pageNumbers).then((file) => { if (getSaveAsHandler() !== null) { - var handler = getSaveAsHandler(); + const handler = getSaveAsHandler(); handler(file, 'extractedDocument.pdf'); } else { saveAs(file, 'extractedDocument.pdf'); @@ -90,7 +90,7 @@ const extractPages = (pageNumbers, dispatch) => { onSecondary: () => { extractPagesWithAnnotations(pageNumbers).then((file) => { if (getSaveAsHandler() !== null) { - var handler = getSaveAsHandler(); + const handler = getSaveAsHandler(); handler(file, 'extractedDocument.pdf'); } else { saveAs(file, 'extractedDocument.pdf');