Complete WPS WPP picture replacement adaptation - #1
Draft
Dongsidaye wants to merge 26 commits into
Draft
Conversation
…Slide.Export (v1.1.6) WPS JSAPI has no Shape.SaveAsPicture method and no PictureFormat.Crop sub-object; both were used by main.js, so every batch operation failed with 'cannot read reference picture'. This change: - exports uncropped signatures and clipboard images through a throw-away presentation + Slide.Export instead of SaveAsPicture - recovers the original picture's natural size from a pasted copy with zeroed crops (Duplicate inside the source deck returns 1x1 in WPS) - normalizes signature exports to a fixed scale so different crop/zoom instances of the same image produce identical hashes - keeps per-instance crop preservation using only documented scalar CropLeft/Right/Top/Bottom properties (probe2-verified math) - adds Copy/Paste retry for clipboard flakiness and clearer errors - verified on WPS WPP 12.1 against real_case_working.pptx: 3 crop variants of the same source image matched and replaced independently, the unrelated 4th picture untouched
…ontext menu - scratch presentation is now created hidden (Presentations.Add(0)) and marked Saved before Close, so batch export no longer flashes a new document window or asks save/discard - single clipboard replacement pastes the image directly onto the target slide and reuses the exact crop-preservation math as file replacement (verified on WPS WPP 12.1: frame and position identical, crops per instance preserved); clipboard batch export caps oversized images so the exported PNG is never stretched - adds a right-click context menu on shapes (ContextMenuShape) with single/batch file and clipboard replacement entries
- New deck-wide image inventory panel (InDesign Links style): group same-source pictures by content fingerprint + aspect, show thumbnails, page number, in-page zone and crop badge. - Replace/update now attach persistent link metadata (PICRENEW|JSON in shape AlternativeText; verified Chinese-safe via COM probe): source path, file fingerprint, content fingerprint, user alt text. - Panel supports mixed group/instance selection -> one-click in-place replace of many pictures while preserving each crop; one-click 'update modified links' after the source file changes on disk; unlink keeps the user's accessibility text; double-click rename writes back to shape.Name; click to jump to the slide. - Clipboard replacement intentionally carries no link metadata. - Hardening: shapes are pre-resolved to live references so index shifts during multi-replace cannot hit the wrong picture; docKey guard rejects stale panel actions after the deck switches; thumbnail cache + aspect guard against fingerprint collisions. - Flag-gated self test (picture_replace_selftest.flag) for automation. - Node mock harness tests/mock_e2e.js: 26 checks, all pass (grouping, link lifecycle, batch regression, same-slide index-shift safety).
- Blank panel root cause: addinUrl guessed the taskpane URL from CurrentWPSAddIn.Path/Name, which WPS reports inconsistently. Switch to the official SDK approach (derive add-in root from document.location, hosted under http://taskpane.html/) with on-disk verification for file:// candidates and a relative-URL fallback. Fixed the file probe off-by-one when stripping the file:/// prefix. - Pane now shows any runtime error inline (global error + unhandled rejection traps) instead of a silent blank pane. - Remove imageMso=TaskPane from ribbon and context menu buttons (WPS renders unknown built-in icons as a question mark).
- Thumbnails: dataURL generation now falls back btoa -> FileReader/Blob -> canvas, with a hashed color placeholder tile when no path works (WPS hosts lack btoa, which silently blanked every tile before). - Grouping: key by content fingerprint only; aspect ratio is no longer part of the group key so non-uniformly scaled instances of the same source image stay together (aspect kept for display only). - Instance rows: show shape name, overlap badge for pictures that fully coincide on the same slide (leftover/duplicate objects), and a hidden badge for invisible shapes. - Tests: 33 assertions (added btoa-less fallback, same-source different-aspect merge, overlap detection).
- Group by 64-bit dHash (8x8 grayscale gradient, Hamming <= 2) computed from the UN-CROPPED full image export, so visually identical sources merge even when WPS/clipboard re-encoded them into different files (real case: same-looking PNGs with different md5, dHash distance 0; different source measured distance 17). Strict byte fingerprint stays as fallback when the host cannot decode images. - The taskpane (CEF) decodes the exported PNG via Image+canvas; ribbon replace paths reuse the same dHash when available. - Mock harness: fake canvas/Image environment, new tests for same-visual-different-bytes merge and different-visual separation; 35 assertions, all pass.
- captureState treated WPS 1x1 placeholders (failed paste -> Duplicate fallback) as valid sizes, silently replacing cropped pictures with an uncropped/stretched result. Now 1x1 is treated as capture failure and replacePictureKeepCrop throws before touching the shape, so the original stays untouched and the panel reports the skipped instance. - Paste retry 3 -> 5; replace/update results now include per-instance failure reasons shown in the panel (page, name, cause). - Mock harness: crop-preservation assertions (frame size + crop values after replace) and failure-report assertions; 39 checks pass.
- WPS exposes PictureFormat on every shape (textbox/autoshape/chart all returned True), so the legacy probe classified non-pictures as images and the panel listed textboxes/graphics; batch-replacing that group then failed halfway. isPicture now judges by shape.Type (13 picture, 11 linked picture; others excluded) and only falls back to the old probe when Type is unavailable. - selectedPicture() uses the same rule so right-click/replace never touches a textbox. - Clearer error when the chosen new image file cannot be read. - Mock harness: textbox/autoshape exclusion + real picture inclusion; 41 checks pass.
WPS does not ship the Office TaskPane imageMso (rendered as a question mark, then removed). Use customUI getImage callback returning an embedded 32x32 PNG (stacked photos + list lines) for both the ribbon large button and the context-menu entry.
- Collect pictures from SlideMaster and every CustomLayout (verified via WPS COM probe: SlideMaster, CustomLayouts, slide.CustomLayout all exposed; slide.Layout is not). - Each master/layout instance reports which slides it applies to by matching slide.CustomLayout names; panel shows template labels and applied-page lists, locate jumps to the first applied page. - Template pictures join the same perceptual-hash grouping and reuse the same in-place replace path (slideOf tolerates master/layout parents). - Mock harness: master/layout collection + applied-pages assertions; 45 checks pass.
- getImage now returns packaged relative PNG paths (WPS drops base64 data URLs, showing question marks); installer bundles the 4 icons - locate for master/layout pictures switches to slide master view (ViewType=11), falls back to first applied slide; slide pictures keep GotoSlide - one-click installer PictureReplaceTools-WPS-1.2.8.exe
- WPS getImage callback uses Id (capital) not id; old dispatcher fell back to one icon for every button. Each button now binds its own getImage callback, so no callback parsing is needed at all - redrew 6 distinct 32x32 icons (panel/file/file-all/clipboard/clipboard-all/info); batch buttons no longer share single-action icons - one-click installer PictureReplaceTools-WPS-1.2.9.exe
- picture list first-open speedup: render up to 36 pictures as a 6x6 grid on one scratch slide and export the grid once (was one export per picture); cells decoded in JS to dHash + RGBA fingerprint + thumbnail, with per-item legacy fallback - scratch presentation is reused across refreshes instead of being created/disposed each time - link status (source file hashes) computed in background after the panel paints; badges flip from 检测中 - flag-gated profiler (%TEMP%\\picture_replace_profile.flag) for measuring scan time - mock E2E updated for grid exports; 45 checks pass
…itance - replacePictureKeepCrop now parses the new image file header (PNG/JPEG/GIF/BMP/WEBP) and uses px*0.75 as the crop baseline instead of AddPicture's capped insert size; large 8000px images no longer shrink crops ~7.6x - clipboard replace reads navigator.clipboard pixel size when available (same 96dpi math), falls back to inserted size - copyCosmetics additionally inherits Reflection, Glow, TransparencyColor, TransparentBackground; saturation/transparency remain out of WPS JSAPI reach - mock E2E: faithful WPS 96dpi model + big-image regression + PNG/JPEG header parser checks; 51 checks pass
- linked shapes skip scratch copy/paste: validate source file fingerprint, read 96dpi baseline straight from file header - batch replace caches file header + thumb/fingerprint per image (one export per batch instead of per shape); z-order adjusted with a single query - inventory batch render 6x6 -> 8x8 (64/export, ~40% fewer exports) - panel progress bar shows phase + count + percent with cancel; ribbon batch ops open a dedicated progress pane (file-based cross-context channel) with cancel - mock E2E: linked fast-path, progress callback, cancel semantics, 8x8 grid; 58 checks pass
- picture list: default sort by same-source usage count desc (master/layout counted by applied pages), also sort by name/source; filters: linked/unlinked/problem/master/crop; name/source search; per-group '应用 N' badge - batch replace progress is now a centered WPS dialog (Application.ShowDialog) that runs the operation in its own context: live bar + count + percent + cancel; taskpane progress kept as fallback - fix frozen-look progress: loops yield to the event loop after each item so progress UIs repaint every picture - addinPageUrl refactor for arbitrary pages; dialog_progress.html packaged in installer - mock E2E 58 checks pass; dialog and sort/filter need real-WPS verification
- clicking 替换选中图片 arms the button (red) and shows '该操作无法撤回,请先保存备份文档!'; a second click within 4s confirms and opens the file picker - mock E2E 58 checks pass
…taller icon + updated confirm text
- Ribbon button 检查更新 opens a taskpane panel that checks GitHub for a newer version (raw manifest, with releases/latest redirect fallback for CN networks) - One-click update downloads the installer exe (PE sanity checked), launches it, and the installer auto-restarts WPS - install-wps.ps1 now keeps authaddin.json path+token in sync and strips stale jspluginonline debug entries - New icon_update.png ribbon icon; mock suite extended to 75 checks
maybeRunViewProbe called trace()/setTracePath() which were never defined, so every add-in load threw a ReferenceError and WPS showed a 'trace is not defined' alert. Added safe no-op trace helpers (writes to tracePath only when a probe flag requests it) and dropped the redundant no-flag trace call. Regression test: OnAddInLoad with no flags must not raise any alert.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
wps_addin/.index.htmlentrypoint required by the currentwpsjs debugflow.Validation
node --check main.jsribbon.xmlandpublish.example.xmlcmd.exe /d /c "echo 1|npx.cmd wpsjs build"npm.cmd audit --omit=dev(0 production vulnerabilities)KWPP.ApplicationCOM availability detected.The current desktop already contains an unsaved WPS document, so clipboard/FileSystem replacement was not executed against that document. The add-in reports its runtime API readiness through the new compatibility diagnostic button.