Skip to content

refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers#333

Merged
balazs-szucs merged 4 commits into
grimmory-tools:developfrom
balazs-szucs:pdf-doc-viewer-fixes
Apr 5, 2026
Merged

refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers#333
balazs-szucs merged 4 commits into
grimmory-tools:developfrom
balazs-szucs:pdf-doc-viewer-fixes

Conversation

@balazs-szucs

@balazs-szucs balazs-szucs commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Description

Linked Issue: Fixes #

Changes

This pull request introduces improvements to the PDF embedding frame, primarily to enhance the handling of Web Workers and WASM initialization for PDFium, as well as to improve logging and configuration flexibility. The changes include a shim for Worker and Blob to patch PDFium's worker initialization, switching to module workers, and enabling more robust logging and error reporting.

Summary by CodeRabbit

  • New Features

    • Added a dismissible document viewer info panel with persistent dismissal.
  • Bug Fixes

    • Improved PDF embed reliability with a runtime shim that enhances worker startup, adds logging, and provides a fallback readiness signal.
    • Normalized WASM resource URL handling to avoid loading inconsistencies.
  • Style

    • Introduced styled, animated info UI and responsive tweaks to hide certain editor controls on small screens.
  • Localization

    • Added translation string for the document viewer info.

@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 185758d0-637c-41f9-bc7d-408f9df17048

📥 Commits

Reviewing files that changed from the base of the PR and between 57375d3 and 905cbc2.

📒 Files selected for processing (1)
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (java-kotlin)

📝 Walkthrough
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the conventional commit format with type 'refactor', scope 'pdf-viewer', and a clear, descriptive subject about worker and blob handling improvements.
Description check ✅ Passed The description follows the required template structure with Description and Changes sections, but the Changes section lacks specific detail about the modifications made to each file.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
frontend/src/assets/embedpdf-frame.html (1)

67-78: String replacement is fragile and could silently fail on PDFium updates.

The exact string matching ('self.postMessage({ type: "wasmError", error: message });' and 'await runner.prepare();') will break if PDFium changes whitespace, quotes, or code structure. Line 78 logs whether the patch was applied, but the code proceeds regardless.

Consider failing loudly or logging a warning when the patch didn't apply, so developers notice when PDFium updates break the shim:

Suggested improvement
         console.log('[Shim] Blob patch applied, changed=' + (patched !== parts[0]));
+        if (patched === parts[0]) {
+          console.warn('[Shim] PDFium blob source did not match expected patterns - worker shim may not function correctly');
+        }
         parts = [patched];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/assets/embedpdf-frame.html` around lines 67 - 78, The current
blob-patching uses fragile exact string replaces for 'self.postMessage({ type:
"wasmError", error: message });' and 'await runner.prepare();' and then always
proceeds; change it so after performing the replacements you check whether the
content actually changed (compare patched !== parts[0]) and if it did not, fail
loudly: emit a clear console.error (or postMessage({type: "shimError", error:
"..."})) and throw an Error to halt startup so developers notice PDFium broke
the shim; keep the existing success log (console.log('[Shim] Blob patch
applied...')) when the patch succeeds and consider using more tolerant matching
(e.g., a focused regex) for 'await runner.prepare()' and the wasmError
postMessage string to reduce future brittleness.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/assets/embedpdf-frame.html`:
- Around line 35-43: The current 5s timeout unconditionally injects a synthetic
'ready' which can mask real WASM init failures; modify the logic around
readySent/wasmInitId/timeout to track whether an 'error' message was received
(e.g., add an errorReceived flag and clear the timeout when a real 'ready' or
'error' arrives), only dispatch the synthetic MessageEvent if no error was
received, and include a marker in the synthetic event data (e.g., data: { type:
'ready', synthetic: true, id: wasmInitId }) so consumers can distinguish
synthetic vs real ready events; ensure the code that sets/clears readySent and
attaches the timeout references readySent, wasmInitId, errorReceived, and
w.dispatchEvent/MessageEvent.

---

Nitpick comments:
In `@frontend/src/assets/embedpdf-frame.html`:
- Around line 67-78: The current blob-patching uses fragile exact string
replaces for 'self.postMessage({ type: "wasmError", error: message });' and
'await runner.prepare();' and then always proceeds; change it so after
performing the replacements you check whether the content actually changed
(compare patched !== parts[0]) and if it did not, fail loudly: emit a clear
console.error (or postMessage({type: "shimError", error: "..."})) and throw an
Error to halt startup so developers notice PDFium broke the shim; keep the
existing success log (console.log('[Shim] Blob patch applied...')) when the
patch succeeds and consider using more tolerant matching (e.g., a focused regex)
for 'await runner.prepare()' and the wasmError postMessage string to reduce
future brittleness.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 56ca59c9-48c5-4b61-8c39-692a8abf6ba7

📥 Commits

Reviewing files that changed from the base of the PR and between bb73dc9 and 9f6a1d1.

📒 Files selected for processing (1)
  • frontend/src/assets/embedpdf-frame.html
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (1)
frontend/src/**/*.{ts,tsx,html,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use 2-space indentation in TypeScript, HTML, and SCSS files

Files:

  • frontend/src/assets/embedpdf-frame.html
🔇 Additional comments (1)
frontend/src/assets/embedpdf-frame.html (1)

262-272: LGTM!

The changes correctly:

  • Normalize the relative wasmUrl to an absolute URL, which is necessary since the iframe context differs from the parent
  • Enable worker mode to leverage the new Worker/Blob shims
  • Enable logging for debugging WASM initialization issues
  • Move style injection to immediately after init to reduce visual flash

Comment thread frontend/src/assets/embedpdf-frame.html

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts (2)

107-108: Wrap localStorage access in try-catch for robustness.

localStorage.getItem() can throw exceptions in restricted environments (private browsing, storage disabled, or quota exceeded). Consider wrapping in a try-catch to prevent runtime errors.

♻️ Proposed fix
-    const dismissed = localStorage.getItem(this.DOC_VIEWER_DISMISSED_KEY);
-    this.isDocViewerInfoVisible = dismissed !== 'true';
+    try {
+      const dismissed = localStorage.getItem(this.DOC_VIEWER_DISMISSED_KEY);
+      this.isDocViewerInfoVisible = dismissed !== 'true';
+    } catch {
+      this.isDocViewerInfoVisible = true;
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts` around
lines 107 - 108, Access to localStorage.getItem(this.DOC_VIEWER_DISMISSED_KEY)
can throw in some environments, so wrap the call in a try-catch around the code
that sets this.isDocViewerInfoVisible; on error fall back to a safe default
(treat as not dismissed or use false) and optionally log the exception, ensuring
DOC_VIEWER_DISMISSED_KEY and isDocViewerInfoVisible semantics remain unchanged.

247-250: Consider adding error handling to localStorage.setItem.

Similar to the read operation, setItem can throw in restricted environments. For consistency and resilience, wrap in try-catch.

♻️ Proposed fix
   dismissDocViewerInfo(): void {
     this.isDocViewerInfoVisible = false;
-    localStorage.setItem(this.DOC_VIEWER_DISMISSED_KEY, 'true');
+    try {
+      localStorage.setItem(this.DOC_VIEWER_DISMISSED_KEY, 'true');
+    } catch {
+      // Ignore storage errors - banner will reappear next session
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts` around
lines 247 - 250, The dismissDocViewerInfo method should guard the localStorage
write against exceptions: wrap the
localStorage.setItem(this.DOC_VIEWER_DISMISSED_KEY, 'true') call in a try-catch
inside dismissDocViewerInfo so the UI state change (this.isDocViewerInfoVisible
= false) still occurs even if setItem throws; in the catch, log or silently
handle the error (e.g., use console.warn or the component's logger) and avoid
rethrowing so callers are not impacted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss`:
- Around line 495-505: The keyframe name docViewerInfoFadeIn violates
Stylelint's keyframes-name-pattern; rename the keyframe to a kebab-case name
(e.g., doc-viewer-info-fade-in) and update all places that reference it (any
animation, animation-name, or shorthand animation declarations in
pdf-reader.component.scss or related style files) to use the new kebab-case
identifier so the `@keyframes` block and its usages remain consistent.

---

Nitpick comments:
In `@frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts`:
- Around line 107-108: Access to
localStorage.getItem(this.DOC_VIEWER_DISMISSED_KEY) can throw in some
environments, so wrap the call in a try-catch around the code that sets
this.isDocViewerInfoVisible; on error fall back to a safe default (treat as not
dismissed or use false) and optionally log the exception, ensuring
DOC_VIEWER_DISMISSED_KEY and isDocViewerInfoVisible semantics remain unchanged.
- Around line 247-250: The dismissDocViewerInfo method should guard the
localStorage write against exceptions: wrap the
localStorage.setItem(this.DOC_VIEWER_DISMISSED_KEY, 'true') call in a try-catch
inside dismissDocViewerInfo so the UI state change (this.isDocViewerInfoVisible
= false) still occurs even if setItem throws; in the catch, log or silently
handle the error (e.g., use console.warn or the component's logger) and avoid
rethrowing so callers are not impacted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c9763a90-1421-4873-a4db-651983fd209f

📥 Commits

Reviewing files that changed from the base of the PR and between 9f6a1d1 and 57375d3.

📒 Files selected for processing (4)
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.html
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
  • frontend/src/i18n/en/reader-pdf.json
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/i18n/en/reader-pdf.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (3)
frontend/src/**/*.{ts,tsx,html,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use 2-space indentation in TypeScript, HTML, and SCSS files

Files:

  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.html
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss
frontend/src/app/**/*.component.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep Angular code on standalone components. Do not add NgModules

Files:

  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
frontend/src/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

frontend/src/app/**/*.{ts,tsx}: Prefer inject() over constructor injection
Follow frontend/eslint.config.js: component selectors use app-*, directive selectors use app*, and any is disallowed

Files:

  • frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts
🪛 Stylelint (17.5.0)
frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss

[error] 495-495: Expected keyframe name "docViewerInfoFadeIn" to be kebab-case (keyframes-name-pattern)

(keyframes-name-pattern)

🔇 Additional comments (4)
frontend/src/app/features/readers/pdf-reader/pdf-reader.component.scss (2)

458-493: LGTM!

The .doc-viewer-info styling is well-structured with appropriate dark theme styling, flex layout, and smooth fade-in animation. The dismiss button hover states provide good visual feedback.


924-937: LGTM!

The mobile responsive adjustments appropriately hide editor tools to simplify the mobile experience and reposition the info banner for centered display on smaller screens.

frontend/src/app/features/readers/pdf-reader/pdf-reader.component.html (1)

24-31: LGTM!

The dismissible info banner is well-structured with proper conditional rendering, i18n support via Transloco, and accessibility through the icon button for dismissal.

frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts (1)

61-62: LGTM!

The state management approach with isDocViewerInfoVisible and the localStorage key constant is clean and follows good practices for dismissible UI elements.

@coderabbitai coderabbitai Bot added frontend and removed feature labels Apr 3, 2026

@zachyale zachyale left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approved pending a follow up issue/note to add localization support in the future

@balazs-szucs balazs-szucs merged commit 46d0655 into grimmory-tools:develop Apr 5, 2026
14 checks passed
zachyale pushed a commit to zachyale/grimmory that referenced this pull request Apr 17, 2026
…ding of wasm PDFium workers (grimmory-tools#333)

* refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers

* feat(doc-viewer): add dismissible info banner for saved changes
zachyale pushed a commit to zachyale/grimmory that referenced this pull request Apr 17, 2026
…ding of wasm PDFium workers (grimmory-tools#333)

* refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers

* feat(doc-viewer): add dismissible info banner for saved changes
zachyale pushed a commit that referenced this pull request Apr 17, 2026
…ding of wasm PDFium workers (#333)

* refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers

* feat(doc-viewer): add dismissible info banner for saved changes
zachyale pushed a commit that referenced this pull request Apr 22, 2026
…ding of wasm PDFium workers (#333)

* refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers

* feat(doc-viewer): add dismissible info banner for saved changes
@coderabbitai coderabbitai Bot mentioned this pull request Apr 26, 2026
2 tasks
dsmouse pushed a commit to dsmouse/grimmory that referenced this pull request May 11, 2026
…ding of wasm PDFium workers (grimmory-tools#333)

* refactor(pdf-viewer): improve worker and blob handling for better loading of wasm PDFium workers

* feat(doc-viewer): add dismissible info banner for saved changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants