Merge pull request #10334 from Snuffleupagus/OpenAction-dest
[api-minor] Add support for OpenAction destinations (issue 10332)
This commit is contained in:
commit
103f4616ac
@ -117,6 +117,10 @@
|
|||||||
],
|
],
|
||||||
"default": 0
|
"default": 0
|
||||||
},
|
},
|
||||||
|
"disableOpenActionDestination": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
"disablePageLabels": {
|
"disablePageLabels": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
@ -392,6 +392,28 @@ class Catalog {
|
|||||||
return shadow(this, 'pageMode', pageMode);
|
return shadow(this, 'pageMode', pageMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get openActionDestination() {
|
||||||
|
const obj = this.catDict.get('OpenAction');
|
||||||
|
let openActionDest = null;
|
||||||
|
|
||||||
|
if (isDict(obj)) {
|
||||||
|
// Convert the OpenAction dictionary into a format that works with
|
||||||
|
// `parseDestDictionary`, to avoid having to re-implement those checks.
|
||||||
|
const destDict = new Dict(this.xref);
|
||||||
|
destDict.set('A', obj);
|
||||||
|
|
||||||
|
const resultObj = { url: null, dest: null, };
|
||||||
|
Catalog.parseDestDictionary({ destDict, resultObj, });
|
||||||
|
|
||||||
|
if (Array.isArray(resultObj.dest)) {
|
||||||
|
openActionDest = resultObj.dest;
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(obj)) {
|
||||||
|
openActionDest = obj;
|
||||||
|
}
|
||||||
|
return shadow(this, 'openActionDestination', openActionDest);
|
||||||
|
}
|
||||||
|
|
||||||
get attachments() {
|
get attachments() {
|
||||||
const obj = this.catDict.get('Names');
|
const obj = this.catDict.get('Names');
|
||||||
let attachments = null;
|
let attachments = null;
|
||||||
|
@ -531,6 +531,10 @@ var WorkerMessageHandler = {
|
|||||||
return pdfManager.ensureCatalog('pageMode');
|
return pdfManager.ensureCatalog('pageMode');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handler.on('getOpenActionDestination', function(data) {
|
||||||
|
return pdfManager.ensureCatalog('openActionDestination');
|
||||||
|
});
|
||||||
|
|
||||||
handler.on('GetAttachments',
|
handler.on('GetAttachments',
|
||||||
function wphSetupGetAttachments(data) {
|
function wphSetupGetAttachments(data) {
|
||||||
return pdfManager.ensureCatalog('attachments');
|
return pdfManager.ensureCatalog('attachments');
|
||||||
|
@ -650,6 +650,14 @@ class PDFDocumentProxy {
|
|||||||
return this._transport.getPageMode();
|
return this._transport.getPageMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Promise} A promise that is resolved with an {Array} containing the
|
||||||
|
* destination, or `null` when no open action is present in the PDF file.
|
||||||
|
*/
|
||||||
|
getOpenActionDestination() {
|
||||||
|
return this._transport.getOpenActionDestination();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {Promise} A promise that is resolved with a lookup table for
|
* @return {Promise} A promise that is resolved with a lookup table for
|
||||||
* mapping named attachments to their content.
|
* mapping named attachments to their content.
|
||||||
@ -2167,6 +2175,11 @@ class WorkerTransport {
|
|||||||
return this.messageHandler.sendWithPromise('GetPageMode', null);
|
return this.messageHandler.sendWithPromise('GetPageMode', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOpenActionDestination() {
|
||||||
|
return this.messageHandler.sendWithPromise('getOpenActionDestination',
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
getAttachments() {
|
getAttachments() {
|
||||||
return this.messageHandler.sendWithPromise('GetAttachments', null);
|
return this.messageHandler.sendWithPromise('GetAttachments', null);
|
||||||
}
|
}
|
||||||
|
@ -650,6 +650,24 @@ describe('api', function() {
|
|||||||
}).catch(done.fail);
|
}).catch(done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('gets default open action destination', function(done) {
|
||||||
|
var loadingTask = getDocument(buildGetDocumentParams('tracemonkey.pdf'));
|
||||||
|
|
||||||
|
loadingTask.promise.then(function(pdfDocument) {
|
||||||
|
return pdfDocument.getOpenActionDestination();
|
||||||
|
}).then(function(dest) {
|
||||||
|
expect(dest).toEqual(null);
|
||||||
|
|
||||||
|
loadingTask.destroy().then(done);
|
||||||
|
}).catch(done.fail);
|
||||||
|
});
|
||||||
|
it('gets non-default open action destination', function(done) {
|
||||||
|
doc.getOpenActionDestination().then(function(dest) {
|
||||||
|
expect(dest).toEqual([{ num: 15, gen: 0, }, { name: 'FitH', }, null]);
|
||||||
|
done();
|
||||||
|
}).catch(done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it('gets non-existent attachments', function(done) {
|
it('gets non-existent attachments', function(done) {
|
||||||
var promise = doc.getAttachments();
|
var promise = doc.getAttachments();
|
||||||
promise.then(function (data) {
|
promise.then(function (data) {
|
||||||
|
17
web/app.js
17
web/app.js
@ -867,7 +867,9 @@ let PDFViewerApplication = {
|
|||||||
|
|
||||||
// Since the `setInitialView` call below depends on this being resolved,
|
// Since the `setInitialView` call below depends on this being resolved,
|
||||||
// fetch it early to avoid delaying initial rendering of the PDF document.
|
// fetch it early to avoid delaying initial rendering of the PDF document.
|
||||||
let pageModePromise = pdfDocument.getPageMode().catch(
|
const pageModePromise = pdfDocument.getPageMode().catch(
|
||||||
|
function() { /* Avoid breaking initial rendering; ignoring errors. */ });
|
||||||
|
const openActionDestPromise = pdfDocument.getOpenActionDestination().catch(
|
||||||
function() { /* Avoid breaking initial rendering; ignoring errors. */ });
|
function() { /* Avoid breaking initial rendering; ignoring errors. */ });
|
||||||
|
|
||||||
this.toolbar.setPagesCount(pdfDocument.numPages, false);
|
this.toolbar.setPagesCount(pdfDocument.numPages, false);
|
||||||
@ -923,8 +925,17 @@ let PDFViewerApplication = {
|
|||||||
}).catch(() => { /* Unable to read from storage; ignoring errors. */ });
|
}).catch(() => { /* Unable to read from storage; ignoring errors. */ });
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
storePromise, pageModePromise,
|
storePromise, pageModePromise, openActionDestPromise,
|
||||||
]).then(async ([values = {}, pageMode]) => {
|
]).then(async ([values = {}, pageMode, openActionDest]) => {
|
||||||
|
if (openActionDest && !this.initialBookmark &&
|
||||||
|
!AppOptions.get('disableOpenActionDestination')) {
|
||||||
|
// Always let the browser history/document hash take precedence.
|
||||||
|
this.initialBookmark = JSON.stringify(openActionDest);
|
||||||
|
// TODO: Re-factor the `PDFHistory` initialization to remove this hack
|
||||||
|
// that's currently necessary to prevent weird initial history state.
|
||||||
|
this.pdfHistory.push({ explicitDest: openActionDest,
|
||||||
|
pageNumber: null, });
|
||||||
|
}
|
||||||
const initialBookmark = this.initialBookmark;
|
const initialBookmark = this.initialBookmark;
|
||||||
// Initialize the default values, from user preferences.
|
// Initialize the default values, from user preferences.
|
||||||
const zoom = AppOptions.get('defaultZoomValue');
|
const zoom = AppOptions.get('defaultZoomValue');
|
||||||
|
@ -48,6 +48,11 @@ const defaultOptions = {
|
|||||||
value: false,
|
value: false,
|
||||||
kind: OptionKind.VIEWER,
|
kind: OptionKind.VIEWER,
|
||||||
},
|
},
|
||||||
|
disableOpenActionDestination: {
|
||||||
|
/** @type {boolean} */
|
||||||
|
value: true,
|
||||||
|
kind: OptionKind.VIEWER,
|
||||||
|
},
|
||||||
disablePageLabels: {
|
disablePageLabels: {
|
||||||
/** @type {boolean} */
|
/** @type {boolean} */
|
||||||
value: false,
|
value: false,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"renderer": "canvas",
|
"renderer": "canvas",
|
||||||
"renderInteractiveForms": false,
|
"renderInteractiveForms": false,
|
||||||
"enablePrintAutoRotate": false,
|
"enablePrintAutoRotate": false,
|
||||||
|
"disableOpenActionDestination": true,
|
||||||
"disablePageMode": false,
|
"disablePageMode": false,
|
||||||
"disablePageLabels": false,
|
"disablePageLabels": false,
|
||||||
"scrollModeOnLoad": 0,
|
"scrollModeOnLoad": 0,
|
||||||
|
@ -94,7 +94,7 @@ class IPDFHistory {
|
|||||||
/**
|
/**
|
||||||
* @param {Object} params
|
* @param {Object} params
|
||||||
*/
|
*/
|
||||||
push({ namedDest, explicitDest, pageNumber, }) {}
|
push({ namedDest = null, explicitDest, pageNumber, }) {}
|
||||||
|
|
||||||
pushCurrentPosition() {}
|
pushCurrentPosition() {}
|
||||||
|
|
||||||
|
@ -158,16 +158,27 @@ class PDFHistory {
|
|||||||
* Push an internal destination to the browser history.
|
* Push an internal destination to the browser history.
|
||||||
* @param {PushParameters}
|
* @param {PushParameters}
|
||||||
*/
|
*/
|
||||||
push({ namedDest, explicitDest, pageNumber, }) {
|
push({ namedDest = null, explicitDest, pageNumber, }) {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((namedDest && typeof namedDest !== 'string') ||
|
if (namedDest && typeof namedDest !== 'string') {
|
||||||
!Array.isArray(explicitDest) ||
|
console.error('PDFHistory.push: ' +
|
||||||
!(Number.isInteger(pageNumber) &&
|
`"${namedDest}" is not a valid namedDest parameter.`);
|
||||||
pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) {
|
|
||||||
console.error('PDFHistory.push: Invalid parameters.');
|
|
||||||
return;
|
return;
|
||||||
|
} else if (!Array.isArray(explicitDest)) {
|
||||||
|
console.error('PDFHistory.push: ' +
|
||||||
|
`"${explicitDest}" is not a valid explicitDest parameter.`);
|
||||||
|
return;
|
||||||
|
} else if (!(Number.isInteger(pageNumber) &&
|
||||||
|
pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) {
|
||||||
|
// Allow an unset `pageNumber` if and only if the history is still empty;
|
||||||
|
// please refer to the `this._destination.page = null;` comment above.
|
||||||
|
if (pageNumber !== null || this._destination) {
|
||||||
|
console.error('PDFHistory.push: ' +
|
||||||
|
`"${pageNumber}" is not a valid pageNumber parameter.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let hash = namedDest || JSON.stringify(explicitDest);
|
let hash = namedDest || JSON.stringify(explicitDest);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user