diff --git a/gulpfile.mjs b/gulpfile.mjs
index 4f3af9d64..496df438b 100644
--- a/gulpfile.mjs
+++ b/gulpfile.mjs
@@ -203,6 +203,7 @@ function createWebpackAlias(defines) {
"web-pdf_attachment_viewer": "web/pdf_attachment_viewer.js",
"web-pdf_cursor_tools": "web/pdf_cursor_tools.js",
"web-pdf_document_properties": "web/pdf_document_properties.js",
+ "web-pdf_save_cfaz_dialog": "web/pdf_save_cfaz_dialog.js",
"web-pdf_find_bar": "web/pdf_find_bar.js",
"web-pdf_layer_viewer": "web/pdf_layer_viewer.js",
"web-pdf_outline_viewer": "web/pdf_outline_viewer.js",
diff --git a/web/app.js b/web/app.js
index 491761d69..e21e628ee 100644
--- a/web/app.js
+++ b/web/app.js
@@ -69,6 +69,7 @@ import { PasswordPrompt } from "./password_prompt.js";
import { PDFAttachmentViewer } from "web-pdf_attachment_viewer";
import { PDFCursorTools } from "web-pdf_cursor_tools";
import { PDFDocumentProperties } from "web-pdf_document_properties";
+import { PDFSaveCfazDialog } from "web-pdf_save_cfaz_dialog";
import { PDFFindBar } from "web-pdf_find_bar";
import { PDFFindController } from "./pdf_find_controller.js";
import { PDFHistory } from "./pdf_history.js";
@@ -117,6 +118,8 @@ const PDFViewerApplication = {
pdfPresentationMode: null,
/** @type {PDFDocumentProperties} */
pdfDocumentProperties: null,
+ /** @type {PDFSaveCfazDialog} */
+ pdfSaveCfazDialog: null,
/** @type {PDFLinkService} */
pdfLinkService: null,
/** @type {PDFHistory} */
@@ -400,19 +403,19 @@ const PDFViewerApplication = {
const annotationEditorMode = AppOptions.get("annotationEditorMode");
const pageColors =
AppOptions.get("forcePageColors") ||
- window.matchMedia("(forced-colors: active)").matches
+ window.matchMedia("(forced-colors: active)").matches
? {
- background: AppOptions.get("pageColorsBackground"),
- foreground: AppOptions.get("pageColorsForeground"),
- }
+ background: AppOptions.get("pageColorsBackground"),
+ foreground: AppOptions.get("pageColorsForeground"),
+ }
: null;
const altTextManager = appConfig.altTextDialog
? new AltTextManager(
- appConfig.altTextDialog,
- container,
- this.overlayManager,
- eventBus
- )
+ appConfig.altTextDialog,
+ container,
+ this.overlayManager,
+ eventBus
+ )
: null;
const pdfViewer = new PDFViewer({
@@ -500,7 +503,15 @@ const PDFViewerApplication = {
this.overlayManager,
eventBus,
l10n,
- /* fileNameLookup = */ () => this._docFilename
+ /* fileNameLookup = */() => this._docFilename
+ );
+ }
+
+ if (appConfig.saveCfazDialog) {
+ this.pdfSaveCfazDialog = new PDFSaveCfazDialog(
+ appConfig.saveCfazDialog,
+ this.overlayManager,
+ l10n
);
}
@@ -613,9 +624,8 @@ const PDFViewerApplication = {
const { appConfig, eventBus } = this;
let file;
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
- const queryString = document.location.search.substring(1);
- const params = parseQueryString(queryString);
- file = params.get("file") ?? AppOptions.get("defaultUrl");
+ const achiveUrl = document.getElementById('archive_url')?.value;
+ file = achiveUrl ?? AppOptions.get("defaultUrl");
validateFileURL(file);
} else if (PDFJSDev.test("MOZCENTRAL")) {
file = window.location.href;
@@ -1042,6 +1052,99 @@ const PDFViewerApplication = {
throw new Error("PDF document not downloaded.");
},
+ /**
+ * @private
+ */
+ async _sendFileToStorage(directUpload) {
+ return new Promise((resolve, reject) => {
+ directUpload.create((error, blob) => {
+ if (error) {
+ reject(new Error(`Não foi possível atualizar o arquivo. ${error}`));
+ } else {
+ resolve(blob)
+ }
+ })
+ });
+ },
+
+ /**
+ * @private
+ */
+ async _updateArchiveCfaz(archive_id, document_signed_id) {
+ return new Promise((resolve, reject) => {
+ const params = JSON.stringify({ archive: { document: document_signed_id } })
+ let xhr = new XMLHttpRequest();
+ xhr.open('PUT', `/archives/${archive_id}.json`, true);
+
+ const csrfToken = document.head.querySelector("[name='csrf-token']")?.content;
+ if (csrfToken) {
+ xhr.setRequestHeader('X-CSRF-Token', csrfToken);
+ }
+
+ xhr.onload = function () {
+ if (xhr.status === 200) {
+ resolve();
+ } else {
+ reject(new Error("Não foi possível atualizar o arquivo."));
+ }
+ };
+
+ xhr.onerror = function (e) {
+ reject(e);
+ };
+
+ xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.send(params);
+ });
+ },
+
+ async saveCfaz() {
+ if (this._saveInProgress) {
+ return;
+ }
+ this._saveInProgress = true;
+ await this.pdfScriptingManager.dispatchWillSave();
+
+ const ac_url = document.getElementById('active_storage_url')?.value,
+ archive_name = document.getElementById('archive_name')?.value,
+ archiveId = document.getElementById('archive_id')?.value;
+
+ this.pdfSaveCfazDialog?.open();
+ try {
+ this._ensureDownloadComplete();
+
+ const data = await this.pdfDocument.saveDocument();
+ const blob = new Blob([data], { type: "application/pdf" });
+
+ const doc_file = new File([blob], archive_name, { type: "application/pdf" })
+ if(ac_url && archiveId){
+ const directUpload = new ActiveStorage.DirectUpload(doc_file, ac_url)
+ await this._sendFileToStorage(directUpload).then((document)=>{
+ this._updateArchiveCfaz(archiveId, document.signed_id);
+ });
+ }
+
+ this.pdfSaveCfazDialog?.setMessageContent('Arquivo enviado com sucesso.');
+ } catch (reason) {
+ // When the PDF document isn't ready, or the PDF file is still
+ // downloading, simply fallback to a "regular" download.
+ this.pdfSaveCfazDialog?.setMessageContent(`Error when saving the document: ${reason.message}`);
+ console.error(`Error when saving the document: ${reason.message}`);
+ // await this.download();
+ } finally {
+ this.pdfSaveCfazDialog?.setCloseButtonToggle(true)
+ await this.pdfScriptingManager.dispatchDidSave();
+ this._saveInProgress = false;
+ }
+
+ if (this._hasAnnotationEditors) {
+ this.externalServices.reportTelemetry({
+ type: "editing",
+ data: { type: "save" },
+ });
+ }
+ },
+
async download(options = {}) {
const url = this._downloadUrl,
filename = this._docFilename;
@@ -1104,6 +1207,9 @@ const PDFViewerApplication = {
}
},
+ backButton() {
+ window.history.back();
+ },
/**
* Report the error; used for errors affecting loading and/or parsing of
* the entire PDF document.
@@ -1507,8 +1613,8 @@ const PDFViewerApplication = {
// Provides some basic debug information
console.log(
`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` +
- `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` +
- `(PDF.js: ${version || "?"} [${build || "?"}])`
+ `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` +
+ `(PDF.js: ${version || "?"} [${build || "?"}])`
);
let pdfTitle = info.Title;
@@ -1914,6 +2020,8 @@ const PDFViewerApplication = {
);
eventBus._on("reporttelemetry", webViewerReportTelemetry, { signal });
}
+ eventBus._on("saveCfaz", webViewerSaveCfaz);
+ eventBus._on("backButton", webViewerBackButton);
},
bindWindowEvents() {
@@ -2117,7 +2225,7 @@ const PDFViewerApplication = {
document.blockUnblockOnload?.(false);
// Ensure that this method is only ever run once.
- this._unblockDocumentLoadEvent = () => {};
+ this._unblockDocumentLoadEvent = () => { };
},
/**
@@ -2156,9 +2264,9 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
// Removing of the following line will not guarantee that the viewer will
// start accepting URLs from foreign origin -- CORS headers on the remote
// server must be properly configured.
- if (fileOrigin !== viewerOrigin) {
- throw new Error("file origin does not match viewer's");
- }
+ // if (fileOrigin !== viewerOrigin) {
+ // throw new Error("file origin does not match viewer's");
+ // }
} catch (ex) {
PDFViewerApplication._documentError("pdfjs-loading-error", {
message: ex.message,
@@ -2396,7 +2504,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
// eslint-disable-next-line no-var
var webViewerOpenFile = function (evt) {
- PDFViewerApplication._openFileInput?.click();
+ // PDFViewerApplication._openFileInput?.click();
};
}
@@ -3214,6 +3322,14 @@ function webViewerAnnotationEditorStatesChanged(data) {
PDFViewerApplication.externalServices.updateEditorStates(data);
}
+function webViewerSaveCfaz() {
+ PDFViewerApplication.saveCfaz();
+}
+
+function webViewerBackButton() {
+ PDFViewerApplication.backButton();
+}
+
function webViewerReportTelemetry({ details }) {
PDFViewerApplication.externalServices.reportTelemetry(details);
}
diff --git a/web/app_options.js b/web/app_options.js
index 61311172c..6cb04859d 100644
--- a/web/app_options.js
+++ b/web/app_options.js
@@ -377,10 +377,7 @@ const defaultOptions = {
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
defaultOptions.defaultUrl = {
/** @type {string} */
- value:
- typeof PDFJSDev !== "undefined" && PDFJSDev.test("CHROME")
- ? ""
- : "compressed.tracemonkey-pldi-09.pdf",
+ value: "",
kind: OptionKind.VIEWER,
};
defaultOptions.sandboxBundleSrc = {
@@ -405,7 +402,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
};
defaultOptions.locale = {
/** @type {string} */
- value: navigator.language || "en-US",
+ value: navigator.language || "pt-BR",
kind: OptionKind.VIEWER,
};
} else if (PDFJSDev.test("CHROME")) {
diff --git a/web/pdf_save_cfaz_dialog.js b/web/pdf_save_cfaz_dialog.js
new file mode 100644
index 000000000..e97e9f926
--- /dev/null
+++ b/web/pdf_save_cfaz_dialog.js
@@ -0,0 +1,94 @@
+/**
+ * @typedef {Object} PDFSaveCfazDialogOptions
+ * @property {HTMLDialogElement} dialog - The overlay's DOM element.
+ * @property {Object} message - Message's DOM element.
+ * @property {HTMLButtonElement} closeButton - Button for closing the overlay.
+ */
+
+class PDFSaveCfazDialog {
+ /**
+ * @param {PDFSaveCfazDialogOptions} options
+ * @param {OverlayManager} overlayManager - Manager for the viewer overlays.
+ * @param {EventBus} eventBus - The application event bus.
+ * @param {IL10n} l10n - Localization service.
+ */
+ constructor(
+ { dialog, message, closeButton },
+ overlayManager,
+ l10n,
+ ) {
+ this.dialog = dialog;
+ this.message = message;
+ this.closeButton = closeButton;
+ this.overlayManager = overlayManager;
+ this.l10n = l10n;
+
+ this.#reset();
+
+ // Bind the event listener for the Close button.
+ this.closeButton.addEventListener("click", this.close.bind(this));
+
+ this.overlayManager.register(this.dialog);
+ }
+
+ /**
+ * Set messageContent to show in overlay
+ *
+ * @param {String} messageContent - Message string
+ */
+ setMessageContent(messageContent) {
+ this.messageContent = messageContent;
+
+ this.#updateUI();
+ }
+
+ /**
+ * Set closeButtonToggle to show in overlay
+ *
+ * @param {Boolean} closeButtonToggle - closeButtonToggle Boolean
+ */
+ setCloseButtonToggle(closeButtonToggle) {
+ this.closeButtonToggle = closeButtonToggle;
+
+ this.#updateUI();
+ }
+
+ #reset() {
+ this.closeButtonToggle = false;
+ this.messageContent = "Enviando arquivo ...";
+ }
+
+ /**
+ * Open the document properties overlay.
+ */
+ async open() {
+ this.#reset();
+ this.#updateUI();
+ await Promise.all([
+ this.overlayManager.open(this.dialog),
+ ]);
+ }
+
+ /**
+ * Close the document properties overlay.
+ */
+ async close() {
+ this.overlayManager.close(this.dialog);
+ }
+
+ /**
+ * Always updates all of the dialog fields, to prevent inconsistent UI state.
+ */
+ #updateUI() {
+ this.message.textContent = this.messageContent;
+
+ if(this.closeButtonToggle){
+ this.closeButton.parentElement.style = 'display: block'
+ }
+ else {
+ this.closeButton.parentElement.style = 'display: none'
+ }
+ }
+}
+
+export { PDFSaveCfazDialog };
diff --git a/web/toolbar.js b/web/toolbar.js
index e92b546c4..276faae01 100644
--- a/web/toolbar.js
+++ b/web/toolbar.js
@@ -61,6 +61,8 @@ class Toolbar {
{ element: options.zoomOut, eventName: "zoomout" },
{ element: options.print, eventName: "print" },
{ element: options.download, eventName: "download" },
+ { element: options.saveCfaz, eventName: "saveCfaz" },
+ { element: options.backButton, eventName: "backButton" },
{
element: options.editorFreeTextButton,
eventName: "switchannotationeditormode",
diff --git a/web/viewer.css b/web/viewer.css
index 56a32ad65..b6d5f95ba 100644
--- a/web/viewer.css
+++ b/web/viewer.css
@@ -861,6 +861,14 @@ body {
left: 6px;
}
+.toolbarButton.customButton {
+ width: auto;
+}
+
+.toolbarButton.customButton::before {
+ content: none;
+}
+
.toolbarButton:is(:hover, :focus-visible)::before,
.secondaryToolbarButton:is(:hover, :focus-visible)::before {
background-color: var(--toolbar-icon-hover-bg-color);
diff --git a/web/viewer.html b/web/viewer.html
index 963818a1d..d5999642c 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -21,37 +21,41 @@ Adobe CMap resources are covered by their own copyright but the same license:
See https://github.com/adobe-type-tools/cmap-resources
-->
-
-
-
-
-
-
- PDF.js viewer
-
-
-
-
-
-
-
+
+
+
+
+
+
+ PDF.js viewer
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
- -->
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-