From 3ae2946d57a15872ebce550419fdba28882b104e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Sz=C3=BCcs?= <127139797+balazs-szucs@users.noreply.github.com> Date: Thu, 13 Nov 2025 12:59:11 +0100 Subject: [PATCH 01/10] [V2] refactor(ui): migrate compress/booklet/sign-up to Mantine Checkbox (#4886) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description of Changes - Updated `BookletImpositionSettings` to use Mantine's `Checkbox` for better UI consistency - Replaced manual checkbox implementations with Mantine's `Checkbox` in `CompressSettings` - Added labels and tooltips for enhanced accessibility and usability ### Before: image image image image ### After: image image image image --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) - [ ] 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 --- .../BookletImpositionSettings.tsx | 147 +++++++++--------- .../tools/compress/CompressSettings.tsx | 20 +-- .../proprietary/routes/signup/SignupForm.tsx | 20 +-- 3 files changed, 90 insertions(+), 97 deletions(-) diff --git a/frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx b/frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx index f0c76f04c..d9c668229 100644 --- a/frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx +++ b/frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; -import { Stack, Text, Divider, Collapse, Button, NumberInput } from "@mantine/core"; +import { Stack, Text, Divider, Collapse, Button, NumberInput, Checkbox } from "@mantine/core"; import { BookletImpositionParameters } from "@app/hooks/tools/bookletImposition/useBookletImpositionParameters"; import ButtonSelector from "@app/components/shared/ButtonSelector"; @@ -21,28 +21,27 @@ const BookletImpositionSettings = ({ parameters, onParameterChange, disabled = f {/* Double Sided */} - + { + const isDoubleSided = event.currentTarget.checked; + onParameterChange('doubleSided', isDoubleSided); + // Reset to BOTH when turning double-sided back on + if (isDoubleSided) { + onParameterChange('duplexPass', 'BOTH'); + } else { + // Default to FIRST pass when going to manual duplex + onParameterChange('duplexPass', 'FIRST'); + } + }} + disabled={disabled} + label={ +
+ {t('bookletImposition.doubleSided.label', 'Double-sided printing')} + {t('bookletImposition.doubleSided.tooltip', 'Creates both front and back sides for proper booklet printing')} +
+ } + /> {/* Manual Duplex Pass Selection - only show when double-sided is OFF */} {!parameters.doubleSided && ( @@ -90,47 +89,44 @@ const BookletImpositionSettings = ({ parameters, onParameterChange, disabled = f {/* Right-to-Left Binding */} - + onParameterChange('spineLocation', event.currentTarget.checked ? 'RIGHT' : 'LEFT')} + disabled={disabled} + label={ +
+ {t('bookletImposition.rtlBinding.label', 'Right-to-left binding')} + {t('bookletImposition.rtlBinding.tooltip', 'For Arabic, Hebrew, or other right-to-left languages')} +
+ } + /> {/* Add Border Option */} - + onParameterChange('addBorder', event.currentTarget.checked)} + disabled={disabled} + label={ +
+ {t('bookletImposition.addBorder.label', 'Add borders around pages')} + {t('bookletImposition.addBorder.tooltip', 'Adds borders around each page section to help with cutting and alignment')} +
+ } + /> {/* Gutter Margin */} - + onParameterChange('addGutter', event.currentTarget.checked)} + disabled={disabled} + label={ +
+ {t('bookletImposition.addGutter.label', 'Add gutter margin')} + {t('bookletImposition.addGutter.tooltip', 'Adds inner margin space for binding')} +
+ } + /> {parameters.addGutter && ( {/* Flip on Short Edge */} - + /> {/* Paper Size Note */} diff --git a/frontend/src/core/components/tools/compress/CompressSettings.tsx b/frontend/src/core/components/tools/compress/CompressSettings.tsx index 7a7c93d67..398e0b7b4 100644 --- a/frontend/src/core/components/tools/compress/CompressSettings.tsx +++ b/frontend/src/core/components/tools/compress/CompressSettings.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { Stack, Text, NumberInput, Select, Divider } from "@mantine/core"; +import { Stack, Text, NumberInput, Select, Divider, Checkbox } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { CompressParameters } from "@app/hooks/tools/compress/useCompressParameters"; import ButtonSelector from "@app/components/shared/ButtonSelector"; @@ -123,18 +123,12 @@ const CompressSettings = ({ parameters, onParameterChange, disabled = false }: C {/* Compression Options */} - + onParameterChange('grayscale', event.currentTarget.checked)} + disabled={disabled} + label={t("compress.grayscale.label", "Apply Grayscale for compression")} + />
); diff --git a/frontend/src/proprietary/routes/signup/SignupForm.tsx b/frontend/src/proprietary/routes/signup/SignupForm.tsx index 35caf7764..9e6ac9dc0 100644 --- a/frontend/src/proprietary/routes/signup/SignupForm.tsx +++ b/frontend/src/proprietary/routes/signup/SignupForm.tsx @@ -1,6 +1,7 @@ import { useEffect } from 'react'; import '@app/routes/authShared/auth.css'; import { useTranslation } from 'react-i18next'; +import { Checkbox } from '@mantine/core'; import { SignupFieldErrors } from '@app/routes/signup/SignupFormValidation'; interface SignupFormProps { @@ -133,19 +134,20 @@ export default function SignupForm({ {/* Terms - only show if showTerms is true */} {showTerms && (
- setAgree?.(e.target.checked)} + onChange={(e) => setAgree?.(e.currentTarget.checked)} className="auth-checkbox" + label={ + + {t("legal.iAgreeToThe", 'I agree to all of the')}{' '} + + {t('legal.terms', 'Terms and Conditions')} + + + } /> -
)} From d06391a9275007736cd444f0d857244741793e2b Mon Sep 17 00:00:00 2001 From: James Brunton Date: Thu, 13 Nov 2025 12:11:59 +0000 Subject: [PATCH 02/10] Redesign and enable macOS signing (#4883) # Description of Changes Re-enable macOS signing and tweak so it runs successfully through CI. Also changes the runner to use macOS 15 instead of 13, which was throwing a deprecation warning in GitHub. Note that the runner doesn't affect the minimum target, which I've still got set to 10.15 (no idea if it actually works on 10.15 but let's assume that if it builds it works until someone can test it) --- .github/workflows/tauri-build.yml | 147 ++++++++++++++++------------- frontend/src-tauri/tauri.conf.json | 6 ++ 2 files changed, 86 insertions(+), 67 deletions(-) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index d56c462d0..077704d23 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -47,21 +47,19 @@ jobs: "windows") echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"}]}' >> $GITHUB_OUTPUT ;; - # "macos") - # echo 'matrix={"include":[{"platform":"macos-latest","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-13","args":"--target x86_64-apple-darwin","name":"macos-x86_64"}]}' >> $GITHUB_OUTPUT - # ;; + "macos") + echo 'matrix={"include":[{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"}]}' >> $GITHUB_OUTPUT + ;; "linux") echo 'matrix={"include":[{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT ;; *) - echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT - # Disabled Mac builds: {"platform":"macos-latest","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-13","args":"--target x86_64-apple-darwin","name":"macos-x86_64"} + echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT ;; esac else # For PR/push events, build all platforms - echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT - # Disabled Mac builds: {"platform":"macos-latest","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-13","args":"--target x86_64-apple-darwin","name":"macos-x86_64"} + echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT fi build: @@ -96,7 +94,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: toolchain: stable - targets: ${{ (matrix.platform == 'macos-latest' || matrix.platform == 'macos-13') && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + targets: ${{ (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} @@ -183,80 +181,96 @@ jobs: working-directory: ./frontend run: npm install - # Disabled Mac builds - Import Apple Developer Certificate - # - name: Import Apple Developer Certificate - # if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-13' - # env: - # APPLE_ID: ${{ secrets.APPLE_ID }} - # APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - # APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - # APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - # KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - # run: | - # echo "Importing Apple Developer Certificate..." - # echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 - # security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain - # security default-keychain -s build.keychain - # security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain - # security set-keychain-settings -t 3600 -u build.keychain - # security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign - # security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain - # security find-identity -v -p codesigning build.keychain - # - name: Verify Certificate - # if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-13' - # run: | - # echo "Verifying Apple Developer Certificate..." - # CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application") - # echo "Certificate Info: $CERT_INFO" - # CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}') - # echo "Certificate ID: $CERT_ID" - # echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV - # echo "Certificate imported." + - name: Import Apple Developer Certificate + if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel' + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + run: | + echo "Importing Apple Developer Certificate..." + echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 + # Create temporary keychain + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + KEYCHAIN_PASSWORD=$(openssl rand -base64 32) + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + # Import certificate + security import certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + # Clean up + rm certificate.p12 - # - name: Check DMG creation dependencies (macOS only) - # if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-13' - # run: | - # echo "🔍 Checking DMG creation dependencies on ${{ matrix.platform }}..." - # echo "hdiutil version: $(hdiutil --version || echo 'NOT FOUND')" - # echo "create-dmg availability: $(which create-dmg || echo 'NOT FOUND')" - # echo "Available disk space: $(df -h /tmp | tail -1)" - # echo "macOS version: $(sw_vers -productVersion)" - # echo "Available tools:" - # ls -la /usr/bin/hd* || echo "No hd* tools found" + - name: Verify Certificate + if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel' + run: | + echo "Verifying Apple Developer Certificate..." + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + CERT_INFO=$(security find-identity -v -p codesigning $KEYCHAIN_PATH | grep "Developer ID Application") + echo "Certificate Info: $CERT_INFO" + CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}') + echo "Certificate ID: $CERT_ID" + echo "APPLE_SIGNING_IDENTITY=$CERT_ID" >> $GITHUB_ENV + echo "Certificate imported successfully." - - name: Build Tauri app + - name: Check DMG creation dependencies (macOS only) + if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel' + run: | + echo "🔍 Checking DMG creation dependencies on ${{ matrix.platform }}..." + echo "hdiutil version: $(hdiutil --version || echo 'NOT FOUND')" + echo "create-dmg availability: $(which create-dmg || echo 'NOT FOUND')" + echo "Available disk space: $(df -h /tmp | tail -1)" + echo "macOS version: $(sw_vers -productVersion)" + echo "Available tools:" + ls -la /usr/bin/hd* || echo "No hd* tools found" + + - name: Build Tauri app uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }} + APPLE_SIGNING_IDENTITY: ${{ env.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPIMAGETOOL_SIGN_PASSPHRASE: ${{ secrets.APPIMAGETOOL_SIGN_PASSPHRASE }} SIGN: 1 - CI: true + CI: true with: projectPath: ./frontend tauriScript: npx tauri args: ${{ matrix.args }} - + + - name: Verify notarization (macOS only) + if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel' + run: | + echo "🔍 Verifying notarization status..." + cd ./frontend/src-tauri/target + DMG_FILE=$(find . -name "*.dmg" | head -1) + if [ -n "$DMG_FILE" ]; then + echo "Found DMG: $DMG_FILE" + echo "Checking notarization ticket..." + spctl -a -vvv -t install "$DMG_FILE" || echo "⚠️ Notarization check failed or not yet complete" + stapler validate "$DMG_FILE" || echo "⚠️ No notarization ticket attached" + else + echo "⚠️ No DMG file found to verify" + fi + - name: Rename artifacts shell: bash run: | mkdir -p ./dist cd ./frontend/src-tauri/target - + # Find and rename artifacts based on platform if [ "${{ matrix.platform }}" = "windows-latest" ]; then find . -name "*.exe" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.exe" \; find . -name "*.msi" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.msi" \; - # Disabled Mac builds - # elif [ "${{ matrix.platform }}" = "macos-latest" ] || [ "${{ matrix.platform }}" = "macos-13" ]; then - # find . -name "*.dmg" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.dmg" \; - # find . -name "*.app" -exec cp -r {} "../../../dist/Stirling-PDF-${{ matrix.name }}.app" \; + elif [ "${{ matrix.platform }}" = "macos-15" ] || [ "${{ matrix.platform }}" = "macos-15-intel" ]; then + find . -name "*.dmg" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.dmg" \; + find . -name "*.app" -exec cp -r {} "../../../dist/Stirling-PDF-${{ matrix.name }}.app" \; else find . -name "*.deb" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.deb" \; find . -name "*.AppImage" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.AppImage" \; @@ -273,7 +287,7 @@ jobs: shell: bash run: | cd ./frontend/src-tauri/target - + # Check for expected artifacts based on platform if [ "${{ matrix.platform }}" = "windows-latest" ]; then echo "Checking for Windows artifacts..." @@ -282,14 +296,13 @@ jobs: echo "❌ No Windows executable found" exit 1 fi - # Disabled Mac builds - # elif [ "${{ matrix.platform }}" = "macos-latest" ] || [ "${{ matrix.platform }}" = "macos-13" ]; then - # echo "Checking for macOS artifacts..." - # find . -name "*.dmg" -o -name "*.app" | head -5 - # if [ $(find . -name "*.dmg" -o -name "*.app" | wc -l) -eq 0 ]; then - # echo "❌ No macOS artifacts found" - # exit 1 - # fi + elif [ "${{ matrix.platform }}" = "macos-15" ] || [ "${{ matrix.platform }}" = "macos-15-intel" ]; then + echo "Checking for macOS artifacts..." + find . -name "*.dmg" -o -name "*.app" | head -5 + if [ $(find . -name "*.dmg" -o -name "*.app" | wc -l) -eq 0 ]; then + echo "❌ No macOS artifacts found" + exit 1 + fi else echo "Checking for Linux artifacts..." find . -name "*.deb" -o -name "*.AppImage" | head -5 @@ -298,7 +311,7 @@ jobs: exit 1 fi fi - + echo "✅ Build artifacts found for ${{ matrix.name }}" - name: Test artifact sizes diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index d845a2dc9..a6dffc881 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -50,6 +50,12 @@ "deb": { "desktopTemplate": "stirling-pdf.desktop" } + }, + "macOS": { + "minimumSystemVersion": "10.15", + "signingIdentity": null, + "entitlements": null, + "providerShortName": null } }, "plugins": { From aa20dbb7a6e4dbab7e7b963c994252431e6359f4 Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Thu, 13 Nov 2025 12:53:57 +0000 Subject: [PATCH 03/10] Feature/v2/selected pageeditor rework (#4756) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) ### 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) - [ ] 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. --------- Co-authored-by: James Brunton Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- frontend/package-lock.json | 58 + frontend/package.json | 1 + .../public/locales/en-GB/translation.json | 6 +- frontend/src/core/components/AppProviders.tsx | 21 +- .../components/layout/Workbench.module.css | 10 +- .../src/core/components/layout/Workbench.tsx | 7 +- .../pageEditor/DragDropGrid.module.css | 72 ++ .../components/pageEditor/DragDropGrid.tsx | 804 +++++++++++-- .../pageEditor/PageEditor.module.css | 42 +- .../core/components/pageEditor/PageEditor.tsx | 1003 ++++++----------- .../pageEditor/PageEditorControls.tsx | 14 +- .../components/pageEditor/PageThumbnail.tsx | 180 +-- .../pageEditor/commands/pageCommands.ts | 55 +- .../core/components/pageEditor/fileColors.ts | 61 + .../hooks/useEditedDocumentState.ts | 249 ++++ .../pageEditor/hooks/useEditorCommands.ts | 420 +++++++ .../pageEditor/hooks/useFileColorMap.ts | 33 + .../hooks/useInitialPageDocument.ts | 22 + .../pageEditor/hooks/usePageDocument.ts | 117 +- .../hooks/usePageEditorDropdownState.ts | 65 ++ .../pageEditor/hooks/usePageEditorExport.ts | 313 +++++ .../pageEditor/hooks/usePageEditorState.ts | 13 +- .../hooks/usePageSelectionManager.ts | 137 +++ .../pageEditor/hooks/useUndoManagerState.ts | 62 + .../pageEditor/pageEditorRightRailButtons.tsx | 16 + .../core/components/shared/AppConfigModal.tsx | 2 - .../shared/HoverActionMenu.module.css | 1 - .../components/shared/HoverActionMenu.tsx | 5 +- .../shared/PageEditorFileDropdown.tsx | 234 ++++ .../src/core/components/shared/Tooltip.tsx | 1 + .../core/components/shared/TopControls.tsx | 123 +- .../shared/pageEditor/useFileItemDragDrop.ts | 154 +++ .../components/tools/compare/compareView.css | 1 + .../tools/overlayPdfs/OverlayPdfsSettings.tsx | 2 - .../tooltips/useSplitSettingsTips.ts | 2 +- .../core/components/viewer/EmbedPdfViewer.tsx | 39 +- .../src/core/contexts/PageEditorContext.tsx | 359 ++++++ .../src/core/contexts/file/FileReducer.ts | 2 + frontend/src/core/hooks/useWheelZoom.ts | 83 ++ frontend/src/core/styles/zIndex.ts | 6 +- frontend/src/core/tools/Split.tsx | 5 +- frontend/src/core/types/fileContext.ts | 13 +- frontend/src/core/types/pageEditor.ts | 10 + 43 files changed, 3833 insertions(+), 990 deletions(-) create mode 100644 frontend/src/core/components/pageEditor/DragDropGrid.module.css create mode 100644 frontend/src/core/components/pageEditor/fileColors.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/useEditedDocumentState.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/useEditorCommands.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/useFileColorMap.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/useInitialPageDocument.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/usePageEditorDropdownState.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/usePageEditorExport.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/usePageSelectionManager.ts create mode 100644 frontend/src/core/components/pageEditor/hooks/useUndoManagerState.ts create mode 100644 frontend/src/core/components/shared/PageEditorFileDropdown.tsx create mode 100644 frontend/src/core/components/shared/pageEditor/useFileItemDragDrop.ts create mode 100644 frontend/src/core/contexts/PageEditorContext.tsx create mode 100644 frontend/src/core/hooks/useWheelZoom.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index deb9b1a05..407f8ca06 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,6 +10,7 @@ "license": "SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", + "@dnd-kit/core": "^6.3.1", "@embedpdf/core": "^1.4.1", "@embedpdf/engines": "^1.4.1", "@embedpdf/plugin-annotation": "^1.4.1", @@ -505,6 +506,63 @@ "node": ">=18" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/accessibility/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@dnd-kit/core": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "license": "MIT", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.1", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/@embedpdf/core": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@embedpdf/core/-/core-1.4.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index b0989a0df..3fa614f35 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,6 +6,7 @@ "proxy": "http://localhost:8080", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", + "@dnd-kit/core": "^6.3.1", "@embedpdf/core": "^1.4.1", "@embedpdf/engines": "^1.4.1", "@embedpdf/plugin-annotation": "^1.4.1", diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index aae5bbc9e..2665b3420 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -1011,7 +1011,8 @@ "title": "Choose Your Split Method" } }, - "selectMethod": "Select a split method" + "selectMethod": "Select a split method", + "resultsTitle": "Split Results" }, "rotate": { "title": "Rotate PDF", @@ -3605,7 +3606,8 @@ "toggleAnnotations": "Toggle Annotations Visibility", "annotationMode": "Toggle Annotation Mode", "draw": "Draw", - "save": "Save" + "save": "Save", + "saveChanges": "Save Changes" }, "search": { "title": "Search PDF", diff --git a/frontend/src/core/components/AppProviders.tsx b/frontend/src/core/components/AppProviders.tsx index 3bf96f29f..24f793188 100644 --- a/frontend/src/core/components/AppProviders.tsx +++ b/frontend/src/core/components/AppProviders.tsx @@ -15,6 +15,7 @@ import { SignatureProvider } from "@app/contexts/SignatureContext"; import { OnboardingProvider } from "@app/contexts/OnboardingContext"; import { TourOrchestrationProvider } from "@app/contexts/TourOrchestrationContext"; import { AdminTourOrchestrationProvider } from "@app/contexts/AdminTourOrchestrationContext"; +import { PageEditorProvider } from "@app/contexts/PageEditorContext"; import ErrorBoundary from "@app/components/shared/ErrorBoundary"; import { useScarfTracking } from "@app/hooks/useScarfTracking"; import { useAppInitialization } from "@app/hooks/useAppInitialization"; @@ -64,15 +65,17 @@ export function AppProviders({ children, appConfigRetryOptions, appConfigProvide - - - - - {children} - - - - + + + + + + {children} + + + + + diff --git a/frontend/src/core/components/layout/Workbench.module.css b/frontend/src/core/components/layout/Workbench.module.css index 602110e4b..73d2e402f 100644 --- a/frontend/src/core/components/layout/Workbench.module.css +++ b/frontend/src/core/components/layout/Workbench.module.css @@ -1,21 +1,21 @@ -.workbench-scrollable { +.workbenchScrollable { overflow-y: auto !important; overflow-x: hidden !important; } -.workbench-scrollable::-webkit-scrollbar { +.workbenchScrollable::-webkit-scrollbar { width: 0.375rem; } -.workbench-scrollable::-webkit-scrollbar-track { +.workbenchScrollable::-webkit-scrollbar-track { background: transparent; } -.workbench-scrollable::-webkit-scrollbar-thumb { +.workbenchScrollable::-webkit-scrollbar-thumb { background-color: var(--mantine-color-gray-4); border-radius: 0.1875rem; } -.workbench-scrollable::-webkit-scrollbar-thumb:hover { +.workbenchScrollable::-webkit-scrollbar-thumb:hover { background-color: var(--mantine-color-gray-5); } diff --git a/frontend/src/core/components/layout/Workbench.tsx b/frontend/src/core/components/layout/Workbench.tsx index 4b3d1ebc8..f6477c67a 100644 --- a/frontend/src/core/components/layout/Workbench.tsx +++ b/frontend/src/core/components/layout/Workbench.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Box } from '@mantine/core'; import { useRainbowThemeContext } from '@app/components/shared/RainbowThemeProvider'; import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; @@ -187,18 +186,16 @@ export default function Workbench() { {/* Main content area */} 0 ? '3.5rem' : '0'), - overflow: currentView === 'viewer' || !isBaseWorkbench(currentView) ? 'hidden' : undefined, }} > {renderMainContent()}