Skip to content

Commit

Permalink
Open files from File Picker & small improvements (#7)
Browse files Browse the repository at this point in the history
* Open files from File Picker & small improvements

- Open files directly from the system's File Picker if the PWA is installed
- Improved the UI in the Settings, using a new "Sections" element for differentiating between tabs
- Improved documentation, by using /** */ for some objects/functions instead of //
- Switched some "let" to "const"

* Update the README with the new React app
  • Loading branch information
dinoosauro authored Apr 21, 2024
1 parent da04909 commit 2304a9e
Show file tree
Hide file tree
Showing 50 changed files with 1,028 additions and 415 deletions.
249 changes: 182 additions & 67 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,75 +1,190 @@
# pdf-pointer
Display PDFs with a pointer, make quick annotations (that automatically disappear), and zoom them

Try it: https://dinoosauro.github.io/pdf-pointer/
Display PDFs with a pointer, make quick annotations (that automatically
disappear), zoom them, and export everything as an image Try it:
https://dinoosauro.github.io/pdf-pointer/

![An example of PDFPointer](./readme-images/example.jpg)

## Open a file
![The welcome screen of PDFPointer](https://i.imgur.com/R94fMa0.png)
When you open the webpage, you'll be asked to open a file. Select a PDF and PDFPointer will automatically display it. You can also drag and drop the file.

At the right, you can see that it's possible to install the app for offline use. See the "Offline Use" section of this README for more information.
## Functions
You can access to all of the functions from the toolbar.
![A screenshot of the toolbar options in PDFPointer](https://i.imgur.com/mAyIlnL.png)

### Draw into a PDF
With PDFPointer, you can create quick annotations that disappear automatically. To do that, click the pen icon from the tools above. Start drawing, and, by default, the annotations will disappear after 15 seconds. If you want to change it, click on the Timer icon and then choosse another option. If you want to erase sooner the drawing, click on the eraser icon. You can also change the color of the drawing tool clicking the _color_ icon next to the erase one.
![A screenshot of a PDF opened in PDFPointer](https://i.imgur.com/ggdGxFW.png)
### Fullscreen
Click on the fullscreen icon (the one after the color one) and the document will be displayed in full screen. The bar will automatically move to the left of the screen.
![An image showing PDFPointer in full screen](https://i.imgur.com/Emsfipt.png)
### Save as image
You can download your PDF with annotations as a JPG/PNG/WebP image by clicking the save image button. You'll be asked the pages to export, the image resolution and its quality (for lossy compression formats). PDFPointer will then export them.

You can also export them in a .zip file. This can be useful if your PDF has lots of pages.

### From the website

When you open the website, you'll be prompted to open a website. Click on the
button and select one of it.

![The UI of the "File picker" page](./readme-images/OpenFile.jpg)

### From the file picker

If you've installed PDFPointer as a Progressive Web App, you can open PDF files
directly from your device's file picker. Right-click the file you want to open,
and select "PDFPointer" from the "Open with" menu. You _could_ also make
PDFPointer the default application for opening PDF files, but honestly neither I
would do that.

## Functionaly

You can access to all functionalities of PDFPointer from the Toolbar
![The toolbar](./readme-images/Toolbar.jpg)

### Previous and next page

The first and the last button permit to change the page. Simple as that.

### Zoom in and out

These buttons permits to change the zoom size. Currently, zoom is
increased/decreased by 0.2

### Show thumbnails

PDFs can have lots of pages. To quickly navigate them, click on the "Show
thumbnails" button to show a preview of each page. Click on each preview to
change page.

### Pen

Create a pen annotation. By clicking it, the pen controls will be shown:

![Pen toolbar](./readme-images/PenToolbar.jpg)

2. Change the annotation timer
3. Change the size of the annotation
4. Change the opacity of the annotation
5. Change the color of the annotation
6. Enable eraser

### Pointer

Change settings about the pointer. By clicking it, the pointer controls will be
shown:

![Pointer toolbar](./readme-images/PointerToolbar.jpg)

2. Change pointer color
3. Change pointer size

### Eraser

Erase both text and pen annotations, by pressing on the part of the canvas to
delete.

### Text

Write text on the PDF. By clicking it, the text controls will be shown:

![Text toolbar](./readme-images/TextToolbar.jpg)

2. Change the text delete timer
3. Change text size
4. Change text color
5. Change text font family
6. Enable/disable bold text
7. Enable/disable italic text
8. Enable/disable underlined text
9. Enable/disable striked text
10. Change underlined/striked bar height
11. Change line spacing
12. Enable eraser mode

### Fullscreen mode

Enable fullscreen mode. If zooms weren't made, the PDF will be adapted to the
screen'size. Otherwise, the zoom size will be adapted to the screen's size
compared to the default (PDF scale)

### PDF Filters

You can add some filters to the PDF to made it easier to read at night. The
filters, adjustable with a slider, are:

- Negative
- Hue inversion
- Sepia
- Grayscale

### Export PDF as image

You can also export the PDF as an array of images. In the new exportation
dropdown, you can specify the number of page to export, the format (and the
quality for lossy formats) and the output screen size.

It's also possible to export all the annotations, applying also the current PDF
filters.

If selected, the PDF images will be exported in a PDF file. Otherwise, if the
browser supports it, the File System API will be used to get direct access to
the output folder, otherwise file will be downloaded as Blob links.

![PDF Export dialog](./readme-images/ExportPDF.jpg)

### Settings
In the settings, you can change lots of things:
- Delete/Add custom colors
- Choose if alerts should be shown (and their length)
- Change the color of the pointer
- [Change, delete or create an application theme](https://github.com/Dinoosauro/pdf-pointer/tree/main/themeCreator)
- Change the zoom option between zooming the PDF canvas or scrolling it; kepp annotations when zooming and enable a button to expand the PDF canvas size.
- Change the background color/image/video of the application.
- Change the language of the application
- See keyboard shortcuts
- See the licenses of the open source libraries
### Zoom in/out
You can zoom the PDF by clicking the magnifying glass icon.
### Expand and contract PDF
Those two strange symbols before the "Next page" one and after the "Previous page" one arte he expand and contract button. These can optionally be enabled by the settings, and allow the user to control in a greater way than zooming the dimension of the canvas where the PDF is displayed. You can use them in both zoom modes.
### Next/Previous page
Click the next/previous icon to go to the next/previous page.

## Offline use
You can use PDFPointer offline by installing the website as a Progressive Web App (currently supported only on Chromium). Make sure to be online the first time and to open a PDF, then everything should work just fine.
## Keyboard shortcuts
The following keyboard shortcuts are supported:
| Key | What it does |
| --- | ---- |
| ⇧ (Shift) | Start (or finish) an annotation |
| ⌥/Alt (Option) | Force stop an annotation |
| ⌫ (Backspace) | Delete an annotation |
| ▶ (Right arrow) | Next page |
| ◀ (Left arrow) | Previous page |
| + (Plus sign) | Increase zoom |
| - (Minus sign) | Decrease zoom |

You can see them also from the website's settings.

## Change background image/video

You can change the background with a local image, the default background color and YouTube videos. Yes, this means you can keep those Minecraft parkour backgrounds also when reading PDF.

![An image showing Minecraft parkour in the background while displaying a PDF.](https://i.imgur.com/LI8VHGd.png)

*The industrial revolution and its consequences...*

Open the settings dialog.

## Privacy
Your PDF files are never uplaoded to the cloud. Everything is elaborated locally on your device.
## Settings

PDFPointer permits to change basically everything about its usage. In the
settings, you can edit:

### Custom color

The new custom colors will appear in the "Fill" dropdowns for pen/text/pointer
colors.

![Custom color tab](./readme-images/CustomColorTab.jpg)

### Custom theme

Manage, apply, create or delete themes.

You can edit each color by clicking on the respective color. Scroll to the right
to see every value, and, at the end of this list, you'll find a button to save
the theme. There are basically no limits to the number of themes you can have.

_Actually, there are: 10^16 themes, or 5MB in the LocalStorage (including other
settings)_

PDFPointer connects to the following domains:
![Custom themes tab](./readme-images/CustomThemesTab.jpg)

### Alerts

Alerts are some text information that appear at the top of the screen. You can
choose to disable them completely, or to hide only some of them. You can also
change the length they are visible.

![Alerts tab](./readme-images/AlertsTab.jpg)

### Language

Change the language used by PDFPointer. Currently, only Italian and English are
supported.

![Language tab](./readme-images/LanguageTab.jpg)

### Background content

You can customize the backgroud content by putting a classic color, an image or
a video (both from local files and from YouTube).

![Background content tab](./readme-images/BackgroundContent.jpg)

_An example of the UI with a custom background can be found at the top of this
README_

### Licenses

Show open source licenses

## Progressive Web App

You can install PDFPointer as a Progressive Web App for a better experience.
You'll also be able to open PDF files directly from the file picker, and you'll
be able to use the website completely offline.

## Privacy

- Google Fonts: to download the fonts used for the text, no data is shared with Google
- JSDelivr/GitHub/CloudFlare: download libraries that make the software work
- GitHub Pages: hosting of pdf-pointer
- YouTube: only if you enable YouTube videos as a background from Settings
Your PDFs stays always on your device. The only external connections made by
PDFPointer are to Google Fonts' servers (and YouTube if you enable a YouTube
video for background content), but no data is shared with them.
5 changes: 2 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@
<body>
<div id="root"></div>
<script>
let positionLink = document.location.href.indexOf("github.io") !== -1 ? `${location.origin}/pdf-pointer/` : `${location.origin}/`;
if ('serviceWorker' in navigator) {
let registration;
const registerServiceWorker = async () => {
registration = await navigator.serviceWorker.register('./service-worker.js', { scope: positionLink });
registration = await navigator.serviceWorker.register('./service-worker.js', { scope: window.location.href.substring(0, window.location.href.lastIndexOf("/") + 1) });
};
registerServiceWorker();
}
let appVersion = "2.0.0";
let appVersion = "2.0.1";
fetch("./pdfpointer-updatecode", { cache: "no-store" }).then((res) => res.text().then((text) => { if (text.replace("\n", "") !== appVersion) if (confirm(`There's a new version of pdf-pointer. Do you want to update? [${appVersion} --> ${text.replace("\n", "")}]`)) { caches.delete("pdfpointer-cache"); location.reload(true); } }).catch((e) => { console.error(e) })).catch((e) => console.error(e)); // Check if the application code is the same as the current application version and, if not, ask the user to update
</script>
<script type="module" src="/src/main.tsx"></script>
Expand Down
38 changes: 23 additions & 15 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
{
"name": "PDFPointer",
"short_name": "PDFPointer",
"start_url": "index.html",
"display": "standalone",
"background_color": "#151515",
"theme_color": "#2c8b9b",
"orientation": "landscape-primary",
"icons": [
{
"src": "./icon.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
"name": "PDFPointer",
"short_name": "PDFPointer",
"start_url": "index.html",
"display": "standalone",
"background_color": "#151515",
"theme_color": "#2c8b9b",
"orientation": "landscape-primary",
"icons": [
{
"src": "./icon.png",
"type": "image/png",
"sizes": "512x512"
}
],
"file_handlers": [
{
"action": "./",
"accept": {
"application/pdf": [".pdf"]
}
}
]
}
2 changes: 1 addition & 1 deletion public/pdfpointer-updatecode
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.0
2.0.1
Binary file added readme-images/AlertsTab.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/BackgroundContent.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/CustomColorTab.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/CustomThemesTab.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/ExportPDF.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/LanguageTab.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/OpenFile.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/PenToolbar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/PointerToolbar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/TextToolbar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/Toolbar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added readme-images/example.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 13 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@ function app() {
if (theme && theme.length !== 0) ThemeManager.apply(theme);
let option = localStorage.getItem("PDFPointer-BackgroundOptions");
if (option !== null) BackgroundManager.apply({ query: option });
if ('launchQueue' in window) { // The user has opened files from the File Explorer
(window.launchQueue as any).setConsumer(async (launchParams: any) => {
if (!launchParams.files.length) return;
getNewState(await launchParams.files[0].getFile());
});
}
}, [])
async function getNewState(file: File) {
let doc = PDFJS.getDocument(await file.arrayBuffer());
document.title = `${file.name} - PDFPointer`;
let res = await doc.promise;
UpdateState(prevState => { return { ...prevState, PDFObj: res } });
}
return <>
<Header></Header><br></br>
{CurrentState.PDFObj === null ? <>
Expand All @@ -36,12 +48,7 @@ function app() {
let input = document.createElement("input");
input.type = "file";
input.onchange = async () => {
if (input.files !== null) {
let doc = PDFJS.getDocument(await input.files[0].arrayBuffer());
document.title = `${input.files[0].name} - PDFPointer`;
let res = await doc.promise;
UpdateState({ ...CurrentState, PDFObj: res });
}
input.files !== null && getNewState(input.files[0]);
}
input.click();
}}>{Lang("Choose file")}</button>
Expand Down
21 changes: 15 additions & 6 deletions src/Components/AlertDom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@ import DropdownItem from "./DropdownItem";
import Lang from "../Scripts/LanguageTranslations";

interface Props {
id: string, // An identifier of the alert category, so that, if the user wants so, it won't be shown again
text: string, // The text contained by the alert
close: () => void // The function that'll handle deleting the element from the DOM
extra?: HTMLElement, // An extra element to add after the text
showSpinner?: boolean // Shows a spinner animation if the alert is for loading content
id: string,
text: string,
close: () => void
extra?: HTMLElement,
showSpinner?: boolean
}
// Shows an alert on the top of the screen
//
/**
* Shows an alert on the top of the screen
* @param id an identifier of the alert category, so that, if the user wants so, it won't be shown again
* @param text the text contained by the alert
* @param close the function that'll handle deleting the element from the DOM
* @param extra an extra element to add after the text
* @param showSpinner shows a spinner animation if the alert is for loading content
* @returns the ReactNode of an alert
*/
export default function AlertDom({ id, text, extra, showSpinner, close }: Props) {
return <>
{showSpinner ? <span className="spinner" style={{ width: "20px", height: "20px" }}></span> : <DynamicImg id="alert"></DynamicImg>}
Expand Down
Loading

0 comments on commit 2304a9e

Please sign in to comment.