Add explicit Save As button for desktop viewer (issue #5928) (#5959)

## 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]>
This commit is contained in:
Achieve3318
2026-03-20 09:32:24 +00:00
committed by GitHub
co-authored by James Brunton
parent a7f2abcb22
commit 55bcb92810
6 changed files with 139 additions and 80 deletions
@@ -2,8 +2,9 @@ import FolderOpenOutlinedIcon from '@mui/icons-material/FolderOpenOutlined';
import SaveOutlinedIcon from '@mui/icons-material/SaveOutlined';
/**
* File action icons for desktop builds
* Overrides core implementation with desktop-appropriate icons
* File action icons for desktop builds.
* Overrides the core implementation with desktop-appropriate icons.
* The presence of `saveAsIconName` signals RightRail to show the Save As button.
*/
export function useFileActionIcons() {
return {
@@ -11,5 +12,8 @@ export function useFileActionIcons() {
download: SaveOutlinedIcon,
uploadIconName: 'folder-rounded' as const,
downloadIconName: 'save-rounded' as const,
// Returning this icon name causes RightRail to render the Save As button.
// On desktop, downloadFile() without a localPath shows a native save dialog.
saveAsIconName: 'save-as-rounded' as string | undefined,
};
}