Skip to content

Enhance PWA support and add PDF tools with caching improvements#45

Merged
sumitsahoo merged 8 commits intomainfrom
dev
Apr 12, 2026
Merged

Enhance PWA support and add PDF tools with caching improvements#45
sumitsahoo merged 8 commits intomainfrom
dev

Conversation

@sumitsahoo
Copy link
Copy Markdown
Owner

This pull request introduces several new PDF tools, updates the tool ordering and descriptions in the UI and documentation, and adds support for service worker-based offline updates. The most significant changes are the addition of three new PDF tools (Split PDF, Extract Images, Compare PDFs), improvements to the user experience for offline/PWA usage, and updates to dependencies to support these features.

New PDF Tools and Features:

  • Added three new tools: Split PDF (divide a PDF into multiple files), Extract Images (extract all embedded images from a PDF), and Compare PDFs (visual diff of two PDFs). These are reflected in both the README.md and the home screen tool grid (src/App.tsx). [1] [2] [3] [4]
  • Updated the README and tool ordering to group tools more logically by function and frequency of use, and clarified descriptions for new and existing tools. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

Progressive Web App (PWA) Enhancements:

  • Introduced a new ReloadPrompt component that notifies users when a new version of the app is available or when offline mode is ready, improving the PWA experience. This component is now rendered globally in the app layout. [1] [2] [3] [4]

Dependency and Configuration Updates:

  • Added the workbox-window dependency to enable service worker registration and update checks for offline/PWA support. [1] [2]

UI and Codebase Organization:

These updates collectively expand the app’s functionality, improve user experience, and lay the groundwork for robust offline support.

Copilot AI review requested due to automatic review settings April 12, 2026 07:54
@sumitsahoo sumitsahoo merged commit ca09e4b into main Apr 12, 2026
6 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands CloakPDF’s toolset with three new PDF utilities (Split PDF, Extract Images, Compare PDFs) and improves the PWA/offline update experience via a new service-worker update prompt and updated PWA configuration.

Changes:

  • Added new PDF tools: Split PDF, Extract Images, and Compare PDFs (wired into the home screen/tool registry).
  • Added a global ReloadPrompt to surface “offline ready” and “update available” PWA states, and adjusted PWA registration strategy.
  • Updated documentation/marketing assets to reflect the expanded tool count and revised tool grouping.

Reviewed changes

Copilot reviewed 10 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vite.config.ts Switches PWA registration to “prompt” and tweaks Workbox cache/update behavior.
tsconfig.json Adds Vite PWA React type support.
src/utils/pdf-renderer.ts Re-exports configured pdfjsLib for shared PDF.js usage.
src/types.ts Extends ToolId union with the three new tool IDs.
src/tools/SplitPdf.tsx Implements the Split PDF tool with split-point UI and ZIP/PDF downloads.
src/tools/ExtractImages.tsx Implements image extraction via PDF.js operator lists with selection + ZIP download.
src/tools/ComparePdf.tsx Implements visual compare + pixel-diff overlay across pages.
src/components/ReloadPrompt.tsx Adds PWA update/offline toast and periodic update checks.
src/App.tsx Registers the new tools and mounts the global reload prompt.
README.md Updates feature list/tool count and adds the new tools to documentation.
public/icons/og-image.svg Updates OG image copy to reflect the new tool count/taglines.
package.json Adds workbox-window dependency.
pnpm-lock.yaml Locks workbox-window and related dependency graph updates.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +268 to +280
{/* Split button */}
{splitPoints.size > 0 && (
<button
type="button"
onClick={handleSplit}
disabled={processing}
className="w-full bg-primary-600 text-white py-3 px-6 rounded-xl font-medium hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{processing
? "Splitting..."
: `Split into ${parts.length} Part${parts.length !== 1 ? "s" : ""} & Download`}
</button>
)}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The primary action button is only rendered when splitPoints.size > 0, but handleSplit explicitly supports the “no split points” case (parts.length === 1). As written, users can’t trigger the download when they haven’t added any split points (and the code path for parts.length === 1 is effectively unreachable from the UI). Consider always rendering the button when a file is loaded (and parts.length > 0), and adjusting the label/UX for the single-part case (e.g., “Download PDF” vs “Split & Download”).

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +24
} = useRegisterSW({
onRegisteredSW(swUrl, registration) {
if (!registration) return;
// Periodically check for new service worker updates
setInterval(async () => {
if (registration.installing || !navigator) return;
if ("connection" in navigator && !navigator.onLine) return;
const resp = await fetch(swUrl, {
cache: "no-store",
headers: { cache: "no-store" },
});
if (resp.status === 200) await registration.update();
}, UPDATE_CHECK_INTERVAL_MS);
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setInterval is started in onRegisteredSW but never cleared, and the async interval callback has no error handling. In dev/HMR or if registration happens more than once, this can create multiple intervals; additionally, if fetch(swUrl) rejects (e.g., offline, captive portal), it can trigger unhandled promise rejections. Consider storing the interval id and clearing it in a cleanup path, checking !navigator.onLine unconditionally (not gated on "connection" in navigator), and wrapping the fetch/registration.update() logic in a try/catch.

Copilot uses AI. Check for mistakes.
pdfjsLib.getDocument({ data: bufB }).promise,
]);

const results = await comparePdfs(pdfA, pdfB, 1.5, (done, total) =>
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleCompare renders every page of both PDFs at scale 1.5, converts each canvas to a PNG data URL, and (when both pages exist) also runs a full getImageData pixel diff. For multi-page or high-resolution PDFs this will be very CPU/memory intensive and can freeze the UI. Consider using a smaller render scale for comparisons/thumbnails, limiting processing to a window around the current page (lazy render/diff on navigation), and/or moving the diff work off the main thread (e.g., worker/OffscreenCanvas) to keep the UI responsive.

Suggested change
const results = await comparePdfs(pdfA, pdfB, 1.5, (done, total) =>
const totalPages = Math.max(pdfA.numPages, pdfB.numPages);
const comparisonScale =
totalPages > 50 ? 0.5 : totalPages > 20 ? 0.65 : totalPages > 10 ? 0.8 : 1;
const results = await comparePdfs(pdfA, pdfB, comparisonScale, (done, total) =>

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants