Update migration plan for PDF.js to DxPdfViewer
Revised `RECEIVER_PDF_VIEWER_CONTEXT.md` to reflect the current status and challenges of migrating from `PDF.js` to `DxPdfViewer`. Replaced the generic migration plan with a detailed post-migration status and recovery plan. Added a breakdown of missing or unreliable features, including page navigation, zoom controls, overlay positioning, signature navigation, thumbnail behavior, and single-page mode. Identified the root cause as the difference between the old `PDF.js`-based platform and the new `DxPdfViewer` component-driven model. Outlined an incremental recovery plan to restore features step-by-step, starting with verifying the `DxPdfViewer` API surface and restoring zoom functionality. Emphasized preserving stable workflow components and avoiding unnecessary refactoring. Provided clear next steps and guidance to rebuild the viewer behavior bridge while maintaining the existing signing workflow.
This commit is contained in:
@@ -543,535 +543,401 @@ A useful way to think about the page is:
|
||||
|
||||
---
|
||||
|
||||
## Detailed Technical Migration Plan: `PDF.js` -> `DxPdfViewer`
|
||||
## Current Post-Migration Status and Step-by-Step Feature Recovery Plan
|
||||
|
||||
This section records the implementation plan for migrating the active receiver signing experience from `PDF.js` to `DxPdfViewer` without losing any workflow behavior.
|
||||
This section replaces the earlier generic migration plan and records the current real status after the first `DxPdfViewer` swap attempt.
|
||||
|
||||
### 1. Core migration principle
|
||||
### 1. Current status summary
|
||||
|
||||
This migration must be treated as:
|
||||
The main document is now visible with `DxPdfViewer`, which means:
|
||||
|
||||
- a **rendering engine replacement**
|
||||
- not a signing workflow redesign
|
||||
- not a simplification to a read-only viewer
|
||||
- not a direct PDF stamping rewrite
|
||||
- receiver authorization still works
|
||||
- document loading still works
|
||||
- the route and page host still work
|
||||
- `DxPdfViewer` is now the visible main rendering surface
|
||||
|
||||
The page-level orchestration in `EnvelopeReceiverPage.razor` remains the source of truth for:
|
||||
However, the receiver experience is currently **feature-incomplete**.
|
||||
|
||||
- receiver authorization
|
||||
- document loading
|
||||
- signature placeholder loading
|
||||
- cached signature loading/saving
|
||||
- popup and validation flow
|
||||
- signature locking rules
|
||||
- reset/restart behavior
|
||||
- toolbar intent
|
||||
At the moment, the page is effectively in this state:
|
||||
|
||||
The rendering layer must be swapped while preserving those behaviors.
|
||||
- PDF is displayed
|
||||
- custom workflow shell still exists
|
||||
- but the old `PDF.js` behavior contract is no longer fully connected to the new viewer
|
||||
|
||||
### 2. Current implementation findings from code
|
||||
So this is no longer a rendering failure.
|
||||
It is now a **behavior recovery** problem.
|
||||
|
||||
Based on the current files:
|
||||
### 2. What is currently missing or unreliable
|
||||
|
||||
- `EnvelopeReceiverPage.razor`
|
||||
- `wwwroot/js/pdf-viewer.js`
|
||||
- `wwwroot/css/envelope-viewer.css`
|
||||
- `EnvelopeReceiverPage_DxPdfViewer.razor`
|
||||
The following features are currently missing, incomplete, or highly likely to be non-functional in the present state.
|
||||
|
||||
the current page is tightly coupled to a custom `pdfViewer` JavaScript object.
|
||||
#### 2.1 Page navigation is not truly connected to `DxPdfViewer`
|
||||
|
||||
That object currently owns all viewer-engine behaviors:
|
||||
Symptoms:
|
||||
|
||||
- PDF load and initialization
|
||||
- current page state
|
||||
- page rendering
|
||||
- zoom rendering
|
||||
- thumbnail rendering
|
||||
- resize listener attachment
|
||||
- signature button rendering
|
||||
- applied signature overlay rendering
|
||||
- signature navigation state
|
||||
- previous page button may update Blazor state only
|
||||
- next page button may update Blazor state only
|
||||
- direct page input may update Blazor state only
|
||||
- thumbnail click may update Blazor state only
|
||||
- signature navigation page jumps may update Blazor state only
|
||||
|
||||
This means the migration cannot be done by replacing only the Razor markup. The current JavaScript object is effectively both:
|
||||
Why:
|
||||
|
||||
- a `PDF.js` adapter
|
||||
- and a receiver-signing overlay controller
|
||||
- the earlier attempt tried to use `ActivePageIndex`, but `DxPdfViewer` does not expose it as a component parameter in this version
|
||||
- after removing that invalid parameter, the page still updates `_currentPage`, but that does not automatically move the DevExpress viewer to another page
|
||||
- in other words, there is currently no verified programmatic page-navigation bridge into `DxPdfViewer`
|
||||
|
||||
Those responsibilities must be separated conceptually during migration.
|
||||
Impact:
|
||||
|
||||
### 3. Verified coordinate and viewport behavior from `PDF.js`
|
||||
- all features that depend on true page switching are blocked or only partially simulated
|
||||
|
||||
Inspection of the `PDF.js` source comments and implementation confirms the following useful facts:
|
||||
#### 2.2 Zoom controls are not truly connected to `DxPdfViewer`
|
||||
|
||||
1. `PageViewport` is created from:
|
||||
- `viewBox`
|
||||
- `scale`
|
||||
- `rotation`
|
||||
- optional offsets
|
||||
Symptoms:
|
||||
|
||||
2. `PDF.js` explicitly documents that `PageViewport` creates a transform that converts:
|
||||
- **PDF coordinate system**
|
||||
- into **normal canvas-like coordinates**
|
||||
- zoom in/out buttons may update `_currentZoom`
|
||||
- slider may update `_currentZoom`
|
||||
- ctrl+wheel logic may update `_currentZoom`
|
||||
- but the visible viewer may not actually zoom accordingly, or may not do so reliably
|
||||
|
||||
3. `PageViewportParameters.viewBox` is documented as:
|
||||
- `xMin, yMin, xMax, yMax`
|
||||
Why:
|
||||
|
||||
4. `getViewport(...)` is documented as returning an object containing:
|
||||
- `width`
|
||||
- `height`
|
||||
- transforms required for rendering
|
||||
- `ZoomLevel` is exposed as a property on `DxPdfViewer`, but it is not yet confirmed that changing the bound value gives the same runtime behavior expected by the old `PDF.js` flow
|
||||
- the current implementation updates Blazor state and triggers overlay refresh, but the real DevExpress zoom lifecycle and its timing have not yet been validated
|
||||
- no verified zoom-changed callback from `DxPdfViewer` has been integrated
|
||||
|
||||
5. `convertToViewportPoint(x, y)` is documented as converting:
|
||||
- PDF coordinates
|
||||
- into viewport coordinates
|
||||
Impact:
|
||||
|
||||
6. `convertToPdfPoint(x, y)` is documented as converting:
|
||||
- viewport coordinates
|
||||
- back into PDF coordinates
|
||||
- specifically useful for converting canvas pixel locations into PDF coordinates
|
||||
- zoom UX is incomplete
|
||||
- overlay synchronization cannot be trusted until real zoom behavior is confirmed
|
||||
|
||||
7. `rawDims` exposes unscaled page dimensions:
|
||||
- `pageWidth`
|
||||
- `pageHeight`
|
||||
- `pageX`
|
||||
- `pageY`
|
||||
#### 2.3 Overlay positioning is heuristic, not yet proven
|
||||
|
||||
8. For rotation `0`, `PageViewport` flips the Y axis into canvas-style coordinates unless `dontFlip` is used.
|
||||
Symptoms:
|
||||
|
||||
### 4. Practical meaning of the current overlay math
|
||||
- signature placeholders may not appear
|
||||
- or may appear in the wrong location
|
||||
- or may not track zoom/page changes correctly
|
||||
|
||||
The current `pdf-viewer.js` implementation does **not** call `convertToViewportPoint(...)` directly.
|
||||
Instead, it uses this simplified mapping:
|
||||
Why:
|
||||
|
||||
- `xPx = sig.x * scale`
|
||||
- `yPx = sig.y * scale`
|
||||
- old implementation owned the page canvas directly
|
||||
- new implementation tries to detect the visible page surface inside `DxPdfViewer` DOM heuristically
|
||||
- this means the current adapter is guessing which DOM element is the active rendered page surface
|
||||
- page geometry, offsets, scaling and scroll surface are not yet bound to a stable DevExpress contract
|
||||
|
||||
This works only because the current upstream data contract already prepares signature coordinates in a way that matches the displayed page layout used by this app.
|
||||
Impact:
|
||||
|
||||
From the wider workspace context, the receiver page data service already converts placeholder coordinates to `UnitOfLength.Point` before they reach the UI.
|
||||
- placeholder buttons are not yet production-safe
|
||||
- applied signatures are not yet production-safe
|
||||
|
||||
Therefore, the active overlay contract is effectively:
|
||||
#### 2.4 Applied signature overlay behavior is not yet dependable
|
||||
|
||||
- incoming signature coordinates are already normalized for the receiver UI
|
||||
- JavaScript currently assumes a top-left, page-relative, point-based overlay space
|
||||
- visual pixel placement is obtained by multiplying by current display scale
|
||||
Symptoms:
|
||||
|
||||
This is extremely important for the migration:
|
||||
- clicking a placeholder may not place the visual signature correctly
|
||||
- applied signatures may drift after zoom
|
||||
- applied signatures may disappear or misalign when navigation changes
|
||||
|
||||
- do **not** casually reinterpret existing signature coordinates as raw PDF bottom-left coordinates
|
||||
- do **not** assume `DxPdfViewer` uses the same visible page coordinate origin
|
||||
- preserve the effective contract already used by the receiver workflow
|
||||
Why:
|
||||
|
||||
### 5. Why the migration is technically hard
|
||||
- applied signatures currently depend on the same unverified geometry bridge as placeholders
|
||||
- they also depend on reliable page identity and zoom identity from the DevExpress surface
|
||||
|
||||
Although both viewers display PDFs, they are fundamentally different integration surfaces.
|
||||
Impact:
|
||||
|
||||
#### Current `PDF.js` model
|
||||
- the core signing UX is not yet restored
|
||||
|
||||
- low-level canvas rendering
|
||||
- direct access to viewport scale
|
||||
- direct control over single page rendering
|
||||
- page DOM is owned by our code
|
||||
- overlays are placed over known custom elements:
|
||||
- `pdf-canvas`
|
||||
- `pdf-text-layer`
|
||||
- `pdf-signature-layer`
|
||||
#### 2.5 Signature navigation is structurally present but functionally blocked
|
||||
|
||||
#### Target `DxPdfViewer` model
|
||||
Symptoms:
|
||||
|
||||
- component-driven render surface
|
||||
- internal DOM is owned by DevExpress
|
||||
- page layout lifecycle is controlled by the component
|
||||
- zoom/page events may differ from `PDF.js`
|
||||
- overlay host placement must be rediscovered or reintroduced
|
||||
- previous/next signature buttons may update internal navigation state
|
||||
- but page-jump and scroll-to-target behavior may fail or be inconsistent
|
||||
|
||||
So the migration is not a `canvas -> component` rename.
|
||||
It is a **viewer capability remapping** problem.
|
||||
Why:
|
||||
|
||||
### 6. Technical target architecture
|
||||
- signature navigation depends on:
|
||||
- real page navigation
|
||||
- real overlay rendering
|
||||
- reliable scroll container discovery
|
||||
- since all three are not yet stabilized, signature navigation cannot yet be trusted
|
||||
|
||||
The target architecture should be treated as four cooperating layers.
|
||||
Impact:
|
||||
|
||||
#### 6.1 Blazor orchestration layer
|
||||
Owned by `EnvelopeReceiverPage.razor`.
|
||||
- navigation across signature fields is not complete
|
||||
|
||||
Remains responsible for:
|
||||
#### 2.6 Thumbnail sidebar is only partially preserved
|
||||
|
||||
- auth and redirect
|
||||
- data loading
|
||||
- signature popup state
|
||||
- signature metadata validation
|
||||
- cached signature reuse
|
||||
- signed/unsigned counts
|
||||
- restart behavior
|
||||
- toolbar user intent
|
||||
What still exists:
|
||||
|
||||
#### 6.2 Viewer host layer
|
||||
Main display surface becomes `DxPdfViewer`.
|
||||
|
||||
This layer must provide equivalents for:
|
||||
|
||||
- document load
|
||||
- current page tracking
|
||||
- total pages tracking
|
||||
- page navigation
|
||||
- zoom control
|
||||
- layout change detection
|
||||
|
||||
#### 6.3 Overlay adapter layer
|
||||
Custom layer that translates page/zoom/layout information into overlay placement.
|
||||
|
||||
This layer must handle:
|
||||
|
||||
- signature placeholder buttons
|
||||
- applied signature overlays
|
||||
- page-relative visibility
|
||||
- redraw after page/zoom/layout changes
|
||||
|
||||
#### 6.4 Thumbnail/navigation support layer
|
||||
Custom or hybrid support for:
|
||||
|
||||
- left sidebar thumbnails
|
||||
- active page highlight
|
||||
- sidebar shell
|
||||
- width persistence
|
||||
- signature previous/next navigation
|
||||
- resize logic
|
||||
- thumbnail rendering through helper pipeline
|
||||
|
||||
### 7. Mandatory first implementation step: extract the current viewer contract
|
||||
What is missing or uncertain:
|
||||
|
||||
Before changing behavior, the following current `pdfViewer` capabilities must be listed and then mapped one-by-one to the target implementation:
|
||||
- guaranteed synchronization between thumbnail click and visible page in `DxPdfViewer`
|
||||
- guaranteed active-page highlight based on real viewer page
|
||||
|
||||
- `initialize`
|
||||
- `getTotalPages`
|
||||
- `getCurrentPage`
|
||||
- `nextPage`
|
||||
- `previousPage`
|
||||
- `goToPage`
|
||||
- `zoomIn`
|
||||
- `zoomOut`
|
||||
- `setScale`
|
||||
- `getScale`
|
||||
- `fitToWidth`
|
||||
- `renderThumbnail`
|
||||
- `attachResizeListeners`
|
||||
- `startResize`
|
||||
- `renderSignatureButtons`
|
||||
- `applySignature`
|
||||
- `getSignatureNavState`
|
||||
- `goToNextSignature`
|
||||
- `goToPreviousSignature`
|
||||
- `dispose`
|
||||
Why:
|
||||
|
||||
The migration should preserve this capability contract at the page level even if the internal engine changes.
|
||||
- active thumbnail currently follows `_currentPage`
|
||||
- but `_currentPage` is not yet guaranteed to reflect the actual active page inside `DxPdfViewer`
|
||||
|
||||
### 8. Planned migration strategy
|
||||
#### 2.7 Single-page behavior is not yet guaranteed to match the old experience
|
||||
|
||||
#### Phase 1 — Confirm the `DxPdfViewer` integration surface
|
||||
Why:
|
||||
|
||||
Use `EnvelopeReceiverPage_DxPdfViewer.razor` as a reference and determine exactly what `DxPdfViewer` exposes for:
|
||||
- old implementation enforced a single active rendered page in a fully custom surface
|
||||
- new implementation uses `DxPdfViewer IsSinglePagePreview="true"`
|
||||
- but this still needs runtime verification against:
|
||||
- page scroll behavior
|
||||
- zoom behavior
|
||||
- page switch timing
|
||||
- overlay surface alignment
|
||||
|
||||
- document content binding
|
||||
- page navigation
|
||||
- current page reading
|
||||
- page change events
|
||||
- zoom setting
|
||||
- zoom change events
|
||||
- page layout readiness
|
||||
- DOM surface that can host overlays
|
||||
### 3. Root cause analysis: why features disappeared
|
||||
|
||||
Key question:
|
||||
The features disappeared for one main reason:
|
||||
|
||||
- can we reliably obtain visible page geometry from the live `DxPdfViewer` DOM?
|
||||
- the old receiver experience was not just a PDF viewer
|
||||
- it was a **custom stateful viewer platform** built on top of `PDF.js`
|
||||
|
||||
If yes, overlays can be positioned relative to the rendered page.
|
||||
If no, a wrapper-based approximation or alternative integration is required.
|
||||
In the old system:
|
||||
|
||||
#### Phase 2 — Replace the main render surface in `EnvelopeReceiverPage.razor`
|
||||
- page navigation was owned by our JavaScript
|
||||
- zoom was owned by our JavaScript
|
||||
- page metrics were owned by our JavaScript
|
||||
- active page surface was owned by our JavaScript
|
||||
- overlays were drawn on DOM elements owned by our JavaScript
|
||||
|
||||
The current custom `canvas + text layer + signature layer` block should be replaced with a `DxPdfViewer` host region while keeping:
|
||||
After the swap:
|
||||
|
||||
- the same page route
|
||||
- the same page state
|
||||
- the same toolbar
|
||||
- the same popup
|
||||
- the same thumbnail sidebar shell
|
||||
- the visible rendering surface belongs to DevExpress
|
||||
- but the custom behavior layer still expects low-level ownership similar to `PDF.js`
|
||||
|
||||
At this stage, only the main document display needs to work.
|
||||
Signature overlays may temporarily be disabled while the host geometry is established.
|
||||
So the missing features are not random regressions.
|
||||
They are the direct result of replacing the renderer before fully rebuilding the viewer behavior bridge.
|
||||
|
||||
#### Phase 3 — Introduce a dedicated overlay host above `DxPdfViewer`
|
||||
### 4. New recommended implementation strategy
|
||||
|
||||
The new viewer surface should be wrapped with a custom page container.
|
||||
Do **not** try to restore everything at once.
|
||||
|
||||
Planned structure:
|
||||
The correct path now is to restore behavior in controlled stages, one capability at a time.
|
||||
|
||||
- outer frame
|
||||
- thumbnail sidebar
|
||||
- splitter
|
||||
- main viewer wrapper
|
||||
- `DxPdfViewer`
|
||||
- absolute-positioned custom overlay layer
|
||||
### 5. Step-by-step recovery plan
|
||||
|
||||
The overlay layer must be independently controlled by our code and not depend on internal `PDF.js` DOM ids.
|
||||
#### Step 1 — Confirm the real `DxPdfViewer` API surface
|
||||
|
||||
#### Phase 4 — Rebuild page/zoom geometry acquisition
|
||||
Goal:
|
||||
|
||||
Because the current implementation derives position using only `sig.x * scale`, the target implementation must determine:
|
||||
- stop guessing which `DxPdfViewer` properties and behaviors are actually bindable and runtime-reactive
|
||||
|
||||
- currently visible page rectangle
|
||||
- page top-left origin inside the wrapper
|
||||
- effective display scale relative to logical point coordinates
|
||||
- current page number
|
||||
Tasks:
|
||||
|
||||
At redraw time, the adapter must produce page-relative pixel coordinates for:
|
||||
- inspect the actual supported parameter surface for the installed DevExpress version
|
||||
- determine which of the following are truly supported and reactive:
|
||||
- zoom binding
|
||||
- page navigation binding
|
||||
- single-page mode behavior
|
||||
- toolbar customization / suppression
|
||||
- determine whether DevExpress exposes any JS/API for page switching or current page retrieval
|
||||
|
||||
- placeholder buttons
|
||||
- applied signature blocks
|
||||
Expected output:
|
||||
|
||||
This should be centralized in one geometry function rather than scattered across multiple viewer actions.
|
||||
- a verified list of what `DxPdfViewer` can really do directly
|
||||
- a list of behaviors that must remain custom because DevExpress does not expose them
|
||||
|
||||
#### Phase 5 — Move signature overlay state to a canonical model
|
||||
This step is mandatory before further feature work.
|
||||
|
||||
The current JavaScript keeps runtime state in:
|
||||
#### Step 2 — Restore real zoom behavior first
|
||||
|
||||
- `signatureButtons`
|
||||
- `appliedSignatures`
|
||||
- `appliedSignatureElements`
|
||||
- `_allSignatures`
|
||||
- `_lastViewedSignatureId`
|
||||
Goal:
|
||||
|
||||
This must remain stable across redraws.
|
||||
- make zoom in/out/slider visibly affect `DxPdfViewer`
|
||||
|
||||
Preferably:
|
||||
Why first:
|
||||
|
||||
- Blazor continues to own the authoritative business state
|
||||
- JavaScript owns transient rendered DOM state only
|
||||
- zoom is simpler than full page navigation
|
||||
- it is also required before overlay sizing can be trusted
|
||||
|
||||
If necessary, applied signature state should be re-sendable from .NET after viewer redraw.
|
||||
That prevents losing visual signatures when page layout changes.
|
||||
Tasks:
|
||||
|
||||
#### Phase 6 — Re-implement signature placeholder rendering on top of `DxPdfViewer`
|
||||
- verify whether `ZoomLevel` binding actually updates the viewer at runtime
|
||||
- if yes, stabilize it
|
||||
- if no, find the supported DevExpress-side mechanism
|
||||
- disable or adjust any overlay refresh logic until true zoom behavior is confirmed
|
||||
|
||||
The current implementation filters placeholders by:
|
||||
Acceptance for this step:
|
||||
|
||||
- current page
|
||||
- not already applied
|
||||
- zoom in button visibly zooms document
|
||||
- zoom out button visibly zooms document
|
||||
- slider visibly changes viewer zoom
|
||||
- `_currentZoom` matches what the user sees
|
||||
|
||||
That same behavior must remain.
|
||||
#### Step 3 — Restore real page navigation
|
||||
|
||||
Rendering rules to preserve:
|
||||
Goal:
|
||||
|
||||
- only placeholders for the active page are shown
|
||||
- already applied placeholders are hidden as buttons
|
||||
- button size grows/shrinks with zoom
|
||||
- button click invokes `.NET` callback `OnSignatureButtonClick`
|
||||
- make previous/next/page input/thumbnail click truly change the visible page in `DxPdfViewer`
|
||||
|
||||
The existing scaling behavior uses `baseScale = 1.5` as the visual reference.
|
||||
That visual convention should be preserved initially unless a new normalized sizing model is intentionally introduced.
|
||||
Tasks:
|
||||
|
||||
#### Phase 7 — Re-implement applied signature rendering on top of `DxPdfViewer`
|
||||
- identify supported page navigation mechanism for this DevExpress version
|
||||
- connect `_currentPage` to the real viewer page
|
||||
- if direct binding is unavailable, create a supported indirect mechanism
|
||||
|
||||
The current applied signature overlay includes:
|
||||
Acceptance for this step:
|
||||
|
||||
- signature image
|
||||
- horizontal separator line
|
||||
- signer full name
|
||||
- optional position
|
||||
- place and date
|
||||
- previous page works
|
||||
- next page works
|
||||
- direct page input works
|
||||
- `_currentPage` reflects visible page
|
||||
|
||||
The same visual block must be retained.
|
||||
This step must be completed before signature navigation or page-specific overlays are considered reliable.
|
||||
|
||||
Required behavior:
|
||||
#### Step 4 — Stabilize active page geometry extraction
|
||||
|
||||
- clicking a placeholder converts it to an applied signature overlay
|
||||
- applied signature remains visible on the correct page
|
||||
- applied signature rescales with zoom
|
||||
- applied signature repositions on page/zoom changes
|
||||
- applied signature is hidden when the user navigates to a different page
|
||||
Goal:
|
||||
|
||||
#### Phase 8 — Re-implement page navigation through a central page-change pipeline
|
||||
- determine a reliable way to identify the active visible rendered page inside the DevExpress DOM
|
||||
|
||||
The following actions must all converge into a single page navigation routine:
|
||||
Tasks:
|
||||
|
||||
- previous page button
|
||||
- next page button
|
||||
- direct page number input
|
||||
- thumbnail click
|
||||
- signature previous/next navigation when target is on another page
|
||||
- inspect the actual DOM produced by `DxPdfViewer`
|
||||
- identify stable selectors for:
|
||||
- viewer scroll container
|
||||
- active page surface
|
||||
- page content bounds
|
||||
- replace heuristic “largest visible element” logic if a more stable pattern exists
|
||||
|
||||
That routine must do all of the following in order:
|
||||
Acceptance for this step:
|
||||
|
||||
1. instruct viewer to change page
|
||||
2. update canonical current page state
|
||||
3. wait for rendered page surface readiness if needed
|
||||
4. redraw placeholder overlays
|
||||
5. refresh signature navigation counter state
|
||||
- geometry retrieval returns correct page bounds repeatedly
|
||||
- geometry remains stable after zoom
|
||||
- geometry remains stable after page changes
|
||||
|
||||
#### Phase 9 — Re-implement zoom through a central zoom-change pipeline
|
||||
#### Step 5 — Restore signature placeholder overlay rendering
|
||||
|
||||
The following actions must converge into one zoom update path:
|
||||
Goal:
|
||||
|
||||
- toolbar zoom in
|
||||
- toolbar zoom out
|
||||
- slider change
|
||||
- fit-to-width
|
||||
- viewer-native zoom events if the user triggers zoom through gestures
|
||||
- make unsigned signature placeholders render at correct positions on the current page
|
||||
|
||||
That routine must:
|
||||
Tasks:
|
||||
|
||||
1. clamp to `50% - 300%`
|
||||
2. update canonical zoom state
|
||||
3. wait for layout/render completion if needed
|
||||
4. redraw placeholder overlays
|
||||
5. rescale applied signatures
|
||||
- connect placeholder rendering to verified page bounds
|
||||
- preserve current filtering rules:
|
||||
- active page only
|
||||
- hide already-signed fields
|
||||
- validate size scaling against visible zoom
|
||||
|
||||
The current implementation already treats redraw after zoom as mandatory. That must remain true.
|
||||
Acceptance for this step:
|
||||
|
||||
#### Phase 10 — Preserve signature navigation independently from the viewer engine
|
||||
- placeholder appears on correct page
|
||||
- placeholder appears in correct location
|
||||
- placeholder size follows zoom
|
||||
|
||||
Current navigation logic is driven by the global ordered signature list and not by PDF rendering internals alone.
|
||||
#### Step 6 — Restore applied signature overlays
|
||||
|
||||
This behavior must remain engine-independent:
|
||||
Goal:
|
||||
|
||||
- previous/next traverses the full signature list
|
||||
- traversal wraps around at the edges
|
||||
- if the target signature is on another page, the viewer jumps first
|
||||
- after page jump, the target element is scrolled into view
|
||||
- toolbar counters reflect total/signed/unsigned/current index
|
||||
- clicking a placeholder should place the actual signature overlay correctly
|
||||
|
||||
If `DxPdfViewer` changes scrolling mechanics, the `scrollToElement` / `scrollToButton` logic must be adapted, but the traversal rules must remain unchanged.
|
||||
Tasks:
|
||||
|
||||
#### Phase 11 — Thumbnail sidebar should remain custom unless `DxPdfViewer` can match all current behavior
|
||||
- keep current visual block format
|
||||
- bind position/size to the same verified geometry system as placeholders
|
||||
- ensure page changes hide/show correctly
|
||||
|
||||
The current sidebar is not just decorative. It also provides:
|
||||
Acceptance for this step:
|
||||
|
||||
- show/hide toggle
|
||||
- click navigation
|
||||
- active page highlight
|
||||
- resizable width
|
||||
- width persistence in `localStorage`
|
||||
- progressive rendering strategy
|
||||
- clicking placeholder places signature correctly
|
||||
- applied signature stays aligned after zoom
|
||||
- applied signature stays aligned after page change
|
||||
|
||||
Because of that, the safest plan is:
|
||||
#### Step 7 — Restore signature navigation
|
||||
|
||||
- keep the custom sidebar shell and resize behavior
|
||||
- only replace the source of main document rendering
|
||||
Goal:
|
||||
|
||||
If `DxPdfViewer` cannot provide matching thumbnails directly, a hybrid solution is acceptable:
|
||||
- previous/next signature should work across all pages again
|
||||
|
||||
- main document rendered by `DxPdfViewer`
|
||||
- thumbnails still generated through a separate custom preview pipeline
|
||||
Tasks:
|
||||
|
||||
This still satisfies the requirement that `DxPdfViewer` becomes the main viewer technology.
|
||||
- keep the existing global signature ordering logic
|
||||
- connect it to real page switching
|
||||
- connect it to real overlay availability
|
||||
- connect it to real scroll-to-target behavior
|
||||
|
||||
#### Phase 12 — Keep signature capture popup unchanged unless integration forces a minimal adjustment
|
||||
Acceptance for this step:
|
||||
|
||||
`receiver-signature.js` and the popup flow should remain mostly untouched.
|
||||
- next signature works on same page
|
||||
- next signature jumps across pages
|
||||
- previous signature works
|
||||
- current index / signed / unsigned counters are correct
|
||||
|
||||
Preserve exactly:
|
||||
#### Step 8 — Validate and finish thumbnail behavior
|
||||
|
||||
- draw tab
|
||||
- text tab
|
||||
- image tab
|
||||
- full name required
|
||||
- place required
|
||||
- signature data required
|
||||
- cached signature reuse
|
||||
- signature change lock after signing starts
|
||||
Goal:
|
||||
|
||||
This area is low-risk and should not be refactored unnecessarily during the viewer migration.
|
||||
- make sidebar behavior trustworthy again
|
||||
|
||||
### 9. File-by-file execution plan
|
||||
Tasks:
|
||||
|
||||
#### `EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverPage.razor`
|
||||
- confirm thumbnails still render correctly
|
||||
- ensure thumbnail click changes actual visible page
|
||||
- ensure active thumbnail reflects actual page
|
||||
- keep width persistence and resize behavior
|
||||
|
||||
Planned work:
|
||||
Acceptance for this step:
|
||||
|
||||
- remove `PDF.js` CDN asset dependency from the active receiver page
|
||||
- replace the custom canvas-based main surface with a `DxPdfViewer` host
|
||||
- preserve toolbar, popup, auth, state and receiver-specific loading logic
|
||||
- redirect viewer method calls through a new or adapted JS interop surface
|
||||
- preserve current state fields wherever possible to minimize workflow regressions
|
||||
- thumbnail click works
|
||||
- active highlight is correct
|
||||
- width persistence still works
|
||||
|
||||
#### `EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/js/pdf-viewer.js`
|
||||
### 6. Recommended order of implementation
|
||||
|
||||
Planned work:
|
||||
The recommended execution order is:
|
||||
|
||||
- split engine-specific logic from workflow-specific logic
|
||||
- remove dependency on direct `pdf-canvas` rendering for the main viewer path
|
||||
- introduce `DxPdfViewer`-compatible geometry and overlay placement helpers
|
||||
- preserve signature navigation logic semantics
|
||||
- preserve overlay rendering semantics
|
||||
- preserve resize integration for sidebar handling
|
||||
1. verify `DxPdfViewer` real API surface
|
||||
2. restore zoom
|
||||
3. restore page navigation
|
||||
4. stabilize page geometry extraction
|
||||
5. restore placeholder overlays
|
||||
6. restore applied signatures
|
||||
7. restore signature navigation
|
||||
8. finish thumbnail synchronization
|
||||
|
||||
This file will likely become a viewer adapter rather than a pure `PDF.js` implementation.
|
||||
This order is important because later features depend on earlier ones.
|
||||
|
||||
#### `EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/envelope-viewer.css`
|
||||
### 7. What should not be changed yet
|
||||
|
||||
Planned work:
|
||||
Until the viewer bridge is stable, avoid refactoring these parts unnecessarily:
|
||||
|
||||
- keep page shell, toolbar, thumbnails, splitter and popup-related styles
|
||||
- replace canvas/text-layer specific assumptions with viewer-wrapper styles
|
||||
- introduce overlay host styles for the `DxPdfViewer` surface
|
||||
- ensure z-index ordering still makes signature buttons clickable
|
||||
- avoid CSS leaking into DevExpress internal DOM more than necessary
|
||||
|
||||
#### `EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverPage_DxPdfViewer.razor`
|
||||
|
||||
Planned role:
|
||||
|
||||
- reference only
|
||||
- used to understand document binding and minimal `DxPdfViewer` setup
|
||||
- not the primary delivery target unless portions are borrowed into the main receiver page
|
||||
|
||||
### 10. Risks that must be explicitly tested during implementation
|
||||
|
||||
1. `DxPdfViewer` may not expose visible page geometry directly.
|
||||
2. `DxPdfViewer` may render asynchronously in a way that requires delayed overlay redraw.
|
||||
3. Built-in zoom/page state may not map 1:1 to current custom toolbar assumptions.
|
||||
4. Sidebar width changes may require explicit overlay recalculation.
|
||||
5. Applied signatures may visually drift if scaling math is not centralized.
|
||||
6. Signature navigation may fail if target DOM nodes are created later than expected.
|
||||
7. Built-in viewer scrolling may differ from the current wrapper scrolling model.
|
||||
|
||||
### 11. Acceptance checklist for the migration
|
||||
|
||||
The migration is only acceptable if all of the following still work in the active page:
|
||||
|
||||
- receiver authorization before document access
|
||||
- document load for the authenticated receiver
|
||||
- single active page viewing
|
||||
- previous/next page navigation
|
||||
- direct page input navigation
|
||||
- thumbnail click navigation
|
||||
- zoom in/out and slider zoom
|
||||
- overlay alignment after zoom changes
|
||||
- signature placeholder rendering on the correct page
|
||||
- placeholder click applying signature overlay
|
||||
- previous/next signature navigation across pages
|
||||
- signed/unsigned counters updating correctly
|
||||
- cached signature reuse
|
||||
- signature popup validation
|
||||
- signature change lock after signing starts
|
||||
- receiver authorization flow
|
||||
- page data loading service
|
||||
- cached signature flow
|
||||
- popup tabs and signature capture JS
|
||||
- signature metadata validation
|
||||
- signature lock behavior
|
||||
- restart signing behavior
|
||||
- thumbnail width persistence
|
||||
|
||||
### 12. Final implementation guidance
|
||||
These parts are not the current problem.
|
||||
|
||||
The correct technical approach is:
|
||||
### 8. Next implementation checkpoint
|
||||
|
||||
- keep `EnvelopeReceiverPage.razor` as the receiver workflow orchestrator
|
||||
- treat `DxPdfViewer` as the new main rendering engine
|
||||
- rebuild overlay placement as a viewer-agnostic custom layer
|
||||
- preserve the current receiver-specific state machine
|
||||
- preserve signature navigation rules
|
||||
- preserve thumbnail/sidebar interaction model where practical
|
||||
The next actual coding step should be:
|
||||
|
||||
In short:
|
||||
- **Step 1 + Step 2** together if possible:
|
||||
- confirm supported `DxPdfViewer` interaction surface
|
||||
- restore real zoom behavior first
|
||||
|
||||
- **replace the renderer**
|
||||
- **preserve the workflow**
|
||||
- **rebuild the overlay adapter**
|
||||
- **do not redesign the signing experience**
|
||||
That is the safest first vertical slice because:
|
||||
|
||||
- it is easy to verify visually
|
||||
- it reduces uncertainty in overlay scaling
|
||||
- it does not yet require full signature flow completion
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user