This patch introduces an abstract `BaseViewer` class, that the existing `PDFViewer` then extends. *Please note:* This lays the necessary foundation for the next patch.
Rather that registering a 'change' event listener on the `window`, which will thus (unnecessarily) fire in *a number* of other situations such as e.g. when the user changes the pageNumber or the current search term, we could/should just register it directly on the dynamically created `fileInput` DOM element instead.
I can see no really compelling reason why we actually need to listen for `file` changes on the `window` itself, and this way we're also able to keep the `fileInput` related code confined to one part of the code which should aid readability.
Furthermore, in custom deployments, there's less risk that we're going to interfere with "outside" code this way.
Finally, preprocessor guards were added to the `webViewerOpenFile` function, since that code doesn't make sense in e.g. the extension builds.
This changes both `PDFViewer` and `PDFThumbnailViewer` to return early in the `pagesRotation` setters if the rotation doesn't change.
It also fixes an existing issue, in `PDFViewer`, that would cause errors if the rotation changes *before* the scale has been set to a non-default value.
Finally, in preparation for subsequent patches, it also refactors the rotation code in `web/app.js` to update the thumbnails and trigger rendering with the new `rotationchanging` event.
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
The current implementation of `PDFHistory` contains a number of smaller bugs, which are *very* difficult to address without breaking other parts of its code.
Possibly the main issue with the current implementation, is that I wrote it quite some time ago, and at the time my understanding of the various edge-cases the code has to deal with was quite limited.
Currently `PDFHistory` may, despite most of those cases being fixed, in certain edge-cases lock-up the browser history, essentially preventing the user from navigating back/forward.
Hence rather than trying to iterate on `PDFHistory` to make it better, the only viable approach is unfortunately rip it out in its entirety and re-write it from scratch.
*It appears that this accidentally broke with PR 8394.*
Currently, the following will be printed in the console:
```
An error occurred while loading the PDF.
[object Promise],[object Promise]
```
With this patch we'll again get proper output, e.g. something with this format:
```
An error occurred while loading the PDF.
PDF.js v? (build: ?)
Message: unknown encryption method
```
Since the very early days of the viewer, it's been possible to pass in a `scale` when opening a PDF file. However, most of the time it was/is actually being ignored, which limits its usefulness considerably.
In older versions of the viewer, if a document hash was present (i.e. `PDFViewerApplication.initialBookmark` being set) or if the document existed in the `ViewHistory`, the `scale` passed to `PDFViewerApplication.open` would thus always be ignored.
In addition to the above, in the current viewer there's even more cases where the `scale` parameter will be ignored: if a (valid) browser history entry exists on document load, or if the `defaultZoomValue` preference is set to a non-default value.
Hence the result is that in most situation, a `scale` passed to `PDFViewerApplication.open` will be completely ignored.
A much better, not to mention supported, way of setting the initial scale is by using the `defaultZoomLevel` preference. In comparision, this also has the advantage of being used in situations where the `scale` would be ignored.
All in all this leads to the current situation where we have code which is essentially dead, since no part of the viewer (by default) relies on it.
To clean up this code, and to avoid having to pass (basically) unused parameters around, I'd thus like to remove the ability to pass a `scale` to `PDFViewerApplication.open`.
Note that the PageMode, as specified in the API, will only be honoured when either: the user hasn't set the `sidebarViewOnLoad` preference to a non-default value, or a non-default `sidebarView` entry doesn't exist in the view history, or the "pagemode" hash parameter is included in the URL.
Since this is new functionality, the patch also includes a preference (`disablePageMode`), to make it easy to opt-out of this functionality if the user/implementor so wishes.
* Check for undefined
new URL(file, window.location.href) throws the following error in IE11 + iPad Safari:
Unable to get property 'replace' of undefined or null reference
* Adapting previous change to pdf.js code standards
Added curly braces
* Moved check for undefined above try/catch
Since we no longer, after PR 8555, allow changing the scale until the document is loaded, that hack is no longer necessary. Furthermore, no part of that event handling function needs to run unless a document is loaded.
The reason that this hack was initially added, is that previously the `ViewHistory` might be updated *before* `PDFViewerApplication.setInitialView` had run (in some cases leading to incorrect inital document scale). Since that is no longer possible, this is now dead code.
These changes consists mainly of replacing `var` with `let`/`const`, adding a couple of default parameters to function signatures, and finally converting `EventBus`/`ProgressBar` to proper classes.
Part of the rotation handling code, in what's now `web/app.js`, hasn't really changed since before the viewer was split into multiple files/components.
Similar to other properties, such as current page/scale, we should probably avoid tracking state in multiple places. Hence I'm suggesting that we don't store the rotation in `PDFViewerApplication`, and access the value in `PDFViewer` instead.
Since `PDFViewerApplication.pageRotation` has existed for a very long time, a getter was added to avoid outright breaking third-party code that may depend on it.
Since this call occurs *before* the `PDFViewer.setDocument` call, it won't actually cause any scale change.
Furthermore, moving it should not be necessary, since the `scale` is already used as the fallback case in `PDFViewerApplication.setInitialView` (provided it's non-zero, which isn't even the case in the default viewer).
Hence this patch should cause no functional changes at all, since it simply removes a piece of unnecessary code.
Currently, these properties are reset in what appears to be somewhat arbitrary locations (within the `load` and `open` methods respectively). The explanation is probably that both of these properties predates the existence of any centralized clean-up code in the viewer.
Hence I think that it makes sense to move the resetting of these properties to the `close` method, since that improves the overview of what's actually cleaned-up/reset when changing documents in the viewer.
With the current way that the `HandTool` is implemented, if someone would try to also add a Zoom tool (as issue 1260 asks for) that probably wouldn't work very well given that you'd then have two cursor tools which may not play nice together.
Hence this patch, which attempts to refactor things so that it should be simpler to add e.g. a Zoom tool as well (given that that issue is marked as "good-beginner-bug", and I'm not sure if that really applies considering the current state of the code).
Note that I personally have no interest in implementing a Zoom tool (similar to Adobe Reader) since I wouldn't use it, but I figured that it can't hurt to make this code a bit more future proof.
Also replaces `var` with `let` in the functions/methods that are touched in the patch. Please note that this should be completely safe, for two separate reasons, since trying to access `let` in a scope where it's not defined is first of all a runtime error and second of all an ESLint error (thanks to the `no-undef` rule).
This patch contains the following improvements:
- Only fetch the various document properties *once* per PDF file opened, and cache the result (in a frozen object).
- Always update the *entire* dialog at once, to prevent inconsistent UI state (issue 8371).
- Ensure that the dialog, and all its internal properties, are reset when `PDFViewerApplication.close` is called.
- Inline, and re-factor, the `getProperties` method in `open`, since that's the only call-site.
- Always overwrite the fileSize with the value obtained from `pdfDocument.getDownloadInfo`, to ensure that it's correct.
- ES6-ify the code that's touched in this patch.
Fixes 8371.
Please see http://eslint.org/docs/rules/object-shorthand.
For the most part, these changes are of the search-and-replace kind, and the previously enabled `no-undef` rule should complement the tests in helping ensure that no stupid errors crept into to the patch.
Rather than having to manually use `initializedPromise`, which really ought to be a private property, to ensure that setting/getting values in the `ViewHistory` works as intended, this re-factoring simply changes all of its methods to be asynchronous.
Furthermore, a `getMultiple` method (mirroring the existing `setMultiple` one) is also added to `ViewHistory`.
Finally, this patch also addresses an existing issue, where certain preferences (e.g. the default zoom level) would be ignored when calling `setInitialView` if reading from the `ViewHistory` fails for some reason.
Note that as discussed on IRC, this makes the viewer slightly slower to load *only* in `gulp server` mode, however the difference seem slight enough that I think it will be fine.
The download method (and the PDF document properties) detect the
file name using `getPDFFileNameFromURL`. The title ought to also
display the PDF filename if available.