Skip to content

Complete WPS WPP picture replacement adaptation - #1

Draft
Dongsidaye wants to merge 26 commits into
masterfrom
agent/wps-adaptation-1-1-1
Draft

Complete WPS WPP picture replacement adaptation#1
Dongsidaye wants to merge 26 commits into
masterfrom
agent/wps-adaptation-1-1-1

Conversation

@Dongsidaye

Copy link
Copy Markdown
Owner

What changed

  • Add a standalone WPS WPP JavaScript add-in under wps_addin/.
  • Preserve per-instance crop geometry, crop focus, position, size, rotation, flips, z-order, name and alt text.
  • Support single and multi-slide same-source replacement from a file or clipboard.
  • Add WPS runtime capability diagnostics and batch matched/success/failed reporting.
  • Add the minimal index.html entrypoint required by the current wpsjs debug flow.

Validation

  • node --check main.js
  • XML parse for ribbon.xml and publish.example.xml
  • cmd.exe /d /c "echo 1|npx.cmd wpsjs build"
  • npm.cmd audit --omit=dev (0 production vulnerabilities)
  • WPS WPP 12.1.0.28043 installation and KWPP.Application COM 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.

…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
- 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.
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.

1 participant