please merge #5919, alternatively, just push this and delete that PR
because this is a continuation of that.
This PR bumps the embed PDF version to 2.8.0 and also adds comments
functionaliy
---------
Co-authored-by: ConnorYoh <[email protected]>
Co-authored-by: Anthony Stirling <[email protected]>
# Description of Changes
Currently, cmd-r is set to rotate the PDF in the viewer instead of
perform refresh in the browser. This is unintuitive and confusing for
Mac users, and for Windows users (who are less used to doing ctrl-r for
refresh) it only works some of the time, if the Viewer is active, so
removing the override is no great loss.
## Description
Adds an explicit **“Save As”** button to the desktop viewer so users can
always save a copy of the current PDF to a different location, even if
the original file already has a local path.
This complements the existing smart **Save/Download** behavior:
- The existing download button continues to either save back to the
original path (when available) or prompt for a path when needed.
- The new **Save As** button always opens a save dialog to choose a
location/name for a new copy.
## Changes
- **RightRail (viewer controls)**
- Added a new **Save As** action icon in the right rail settings
section.
- The button:
- Uses `viewerContext.exportActions.saveAsCopy()` to get the current
viewer state as a PDF.
- Calls `downloadFile` without a `localPath`, ensuring the desktop app
shows a **Save As** dialog.
- Picks the first selected file (if any) or the first active file as the
source for the filename.
- **Desktop / Web behavior**
- In the desktop app (Tauri), clicking **Save As**:
- Opens a native save dialog so the user can choose a different folder
and filename.
- Writes a new copy without changing the existing file’s `localFilePath`
or dirty state.
- In the web app, the button behaves like a standard download of a copy
(browser-controlled save dialog / download).
## Motivation
- Users often want to apply operations on a PDF while **keeping the
original unmodified**.
- The existing smart Save behavior chooses between Save and Save As
automatically, but there was no way to explicitly request **Save As**.
- This change gives desktop users a clear, dedicated **“Save As”**
control while preserving the current Save/Download behavior.
## Notes
- No backend changes.
- No changes to the existing Save / Download button behavior.
- The new button uses existing viewer export and download utilities,
minimizing new logic.
---------
Co-authored-by: James Brunton <[email protected]>
Tested:
* Can sign in on saas -> can run local tools with or without credits->
can run saas only tools (if credits) -> can't run saas only tools
without credits
* Can sign in self-hosted -> can run all tools on remote if available ->
can run local when self-hosted unavailable
Clouds show on saas tools when connected
Tools are disabled when connected to self-hosted but cannot find server.
You also get banner
#cantwaitforplaywritetests
# Description of Changes
Fix#5164
As I mentioned on the bug
https://github.com/Stirling-Tools/Stirling-PDF/issues/5164#issuecomment-4045170827,
it's impossible to print on Mac currently because
`iframe.contentWindow?.print()` silently does nothing in Tauri on Mac,
but [it seems unlikely that this will be
fixed](https://github.com/tauri-apps/tauri/issues/13451#issuecomment-4048075861).
Instead, I've linked directly to the Mac `PDFKit` framework in Rust to
use its printing functionality instead of Safari's. I believe that
`PDFKit` is what `Preview.app` is using and the print UI that it
generates seems to perform identically, so this should solve the issue
on Mac. Hopefully one day the TS iframe print API will be fixed and
we'll be able to get rid of this code, or [there'll be an official Tauri
plugin for printing which we can use
instead](https://github.com/tauri-apps/plugins-workspace/issues/293).
This implementation should be entirely Mac-specific. Windows & Linux
will continue to use their TS printing (which comes from EmbedPDF)
unless we have a good reason to change them to use a native solution as
well.
* Text box/notes movement improvements ✅
* Fix the issue where hiding, then showing annotations looses progress ✅
* Fix the issue where hidig/showing annotations jumps you back up to the
top of your open document ✅
* Support ctrl+c and ctrl+v and backspace to delete ✅
* Better handling when moving to different tool from annotate ✅
* Added a color picker eyedropper button ✅
* Auto-switch to Select after note/text placement, so users can quickly
place and type ✅
# Description of Changes
Adds the code for the SaaS frontend as proprietary code to the OSS repo.
This version of the code is adapted from 22/1/2026, which was the last
SaaS version based on the 'V2' design. This will move us closer to being
able to have the OSS products understand whether the user has a SaaS
account, and provide the correct UI in those cases.
* Adds a fallback mechanism so the desktop app routes tool operations to
the local bundled backend when the user's self-hosted Stirling-PDF
server goes offline, and disables tools in the UI that aren't supported
locally.
* `selfHostedServerMonitor.ts` independently polls the self-hosted
server every 15s and exposes which tool endpoints are unavailable when
it goes offline
* `operationRouter.ts` intercepts operations destined for the
self-hosted server and reroutes them to the local bundled backend when
the monitor reports it offline
* `useSelfHostedToolAvailability.ts` feeds the offline tool set into
useToolManagement, disabling affected tools in the UI with a
selfHostedOffline reason and banner warning
- `SelfHostedOfflineBanner `is a dismissable (session-only) gray bar
shown at the top of the UI when in self-hosted mode and the server goes
offline. It shows:
# Description of Changes
Upgrades embedPDF from v2.5.0 to v2.6.0 and migrates from unmaintained
pdf-lib to @cantoo/pdf-lib fork. Adds defensive error handling for
malformed PDFs and improves bridge lifecycle management.
### Changes
**Dependencies**
- Upgrade all @embedpdf/* packages from ^2.5.0 to ^2.6.0
- Replace pdf-lib with @cantoo/pdf-lib (maintained fork with better
TypeScript support)
**PDF Viewer Infrastructure (attachment/bookmark fix)**
- Add useDocumentReady hook to track document lifecycle across bridges
- Implement defensive bridge cleanup to prevent stale registrations
- Fix race condition in document ready state detection by subscribing to
events before checking state
**Link Extraction (updated to cantoo/pdf-lib)**
- Add graceful error handling for PDFs with invalid catalog structures
- Extract enhanced link metadata (tooltips, colors, border styles,
highlight modes)
- Return empty results instead of throwing on malformed PDFs
- Add validation for link creation (destination page bounds, rect
dimensions, color values)
**Signature Flattening (updated to cantoo/pdf-lib)**
- Improve SVG embedding with three-tier fallback strategy (native
vector, rasterized PNG, placeholder)
- Add proper Unicode handling for PDF form tooltips via
PDFString.decodeText()
- Extract SVG utilities into cleaner strategy pattern
**Form Field Processing (updated to cantoo/pdf-lib)**
- Add support for display labels vs export values in dropdown/list
fields per PDF spec 12.7.4.4
- Implement caching for expensive field property lookups
- Add proper handling of malformed /Opt arrays
<!--
Please provide a summary of the changes, including:
- What was changed
- Why the change was made
- Any challenges encountered
Closes #(issue_number)
-->
---
## Checklist
### General
- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### Translations (if applicable)
- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
---------
Signed-off-by: Balázs Szücs <[email protected]>
# Summary
- Adds desktop file tracking: local paths are preserved and save buttons
now work as expcted (doing Save/Save As as appropriate)
- Adds logic to track whether files are 'dirty' (they've been modified
by some tool, and not saved to disk yet).
- Improves file state UX (dirty vs saved) and close warnings
- Web behaviour should be unaffected by these changes
## Indicators
Files now have indicators in desktop mode to tell you their state.
### File up-to-date with disk
<img width="318" height="393" alt="image"
src="https://github.com/user-attachments/assets/06325f9a-afd7-4c2f-8a5b-6d11e3093115"
/>
### File modified by a tool but not saved to disk yet
<img width="357" height="385" alt="image"
src="https://github.com/user-attachments/assets/1a7716d9-c6f7-4d13-be0d-c1de6493954b"
/>
### File not tracked on disk
<img width="312" height="379" alt="image"
src="https://github.com/user-attachments/assets/9cffe300-bd9a-4e19-97c7-9b98bebefacc"
/>
# Limitations
- It's a bit weird that we still have files stored in indexeddb in the
app, which are still loadable. We might want to change this behaviour in
the future
- Viewer's Save doesn't persist to disk. I've left that out here because
it'd need a lot of testing to make sure the logic's right with making
sure you can leave the Viewer with applying the changes to the PDF
_without_ saving to disk
- There's no current way to do Save As on a file that has already been
persisted to disk - it's only ever Save. Similarly, there's no way to
duplicate a file.
---------
Co-authored-by: James Brunton <[email protected]>
Co-authored-by: James Brunton <[email protected]>