Skip to content

Reuse copyright/license metadata + "Add this info to all images" in C&L dialog#7983

Draft
hatton wants to merge 3 commits into
masterfrom
RecentImageMetadata
Draft

Reuse copyright/license metadata + "Add this info to all images" in C&L dialog#7983
hatton wants to merge 3 commits into
masterfrom
RecentImageMetadata

Conversation

@hatton

@hatton hatton commented Jun 19, 2026

Copy link
Copy Markdown
Member

What this does

Adds tools to the Copyright & License dialog for reusing metadata from other images (pull), and causing all other images to get the same metadata as the current image (push).

image
  • Adds Metadata "Shortcuts" chooser — gathers copyright/license metadata from the other images in the book (plus the book's own copyright/license) so the user can apply an existing set with one click instead of retyping. Gathering is progressive (one image at a time) and stops when the dialog closes. The set matching the image's current metadata is shown checked and pinned to the top of the list.
  • "Add this info to all images in this book" button — replaces the old WinForms yes/no "copy to all images?" MessageBox. The dialog stays open and shows a Working… spinner, then a Done confirmation driven by a websocket event when the copy actually finishes.
  • Launch the dialog via the workspace (top window) bundle rather than the page iframe, so saving the metadata (which reloads the page iframe) no longer tears the dialog down.

The reuse chooser is offered only when editing image metadata, not for the book's own copyright/license.

Backend

New read-only endpoints to list the book's creditable image file names and to read a single image's metadata, plus a static ImageApi.GetCreditableImageFileNamesInBook helper.

🤖 Generated with Claude Code

Devin review


This change is Reviewable

…&L dialog

Reworks the Copyright & License dialog for images:

- Adds a "Shortcuts" reuse chooser that gathers copyright/license metadata
  from the other images in the book (plus the book's own copyright/license)
  so the user can apply an existing set with one click instead of retyping.
  Gathering is progressive (one image at a time) and stops when the dialog
  closes. The set matching the image's current metadata is shown checked and
  pinned to the top of the list.

- Replaces the old WinForms yes/no "copy to all images?" MessageBox with an
  in-dialog "Add this info to all images in this book" button. The dialog
  stays open and shows a "Working…" spinner, then a "done" confirmation
  driven by a websocket event when the copy actually finishes.

- Launches the dialog via the workspace (top window) bundle rather than the
  page iframe, so saving the metadata (which reloads the page iframe) no
  longer tears the dialog down.

- BL-16446: reduces the image fileName (which may carry a query string and/or
  URL encoding from the html src attribute) to the on-disk file name before
  loading, so PalasoImage no longer wrongly reports the image as corrupt.

Backend: new read-only endpoints to list the book's creditable image file
names and to read a single image's metadata, plus a static
ImageApi.GetCreditableImageFileNamesInBook helper.

The reuse chooser is only offered when editing image metadata, not for the
book's own copyright/license.

Robustness: the image-metadata POST handler now notifies the dialog that an
"add to all images" request has finished on every path (via a finally and the
wrong-state branch), so the "Working…" spinner can never hang when the copy
doesn't actually run (save failed, non-normal image, or an error).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vy5zgbKXxtYoMeaUxWBhA8
@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds two reuse tools to the Copyright & License dialog: a progressive "Shortcuts" chooser that scans the book's images for existing metadata packages, and an "Add this info to all images" button with a WebSocket-driven working/done state machine. It also moves dialog launch from the page iframe to the workspace bundle so that saving (which reloads the iframe) no longer tears down the dialog.

  • MetadataChooser (MetadataChooser.tsx, metadataReuseUtils.ts) gathers metadata one image at a time, de-duplicates by a stable JSON key, pins the currently-active package to the top, and caps the list height to three visible rows.
  • Push-to-all flow (CopyrightAndLicenseDialog.tsx, CopyrightAndLicenseApi.cs, EditingModel.cs) replaces the old WinForms MessageBox with a button + spinner + done-check pattern; every code path (save failure, non-normal image, image-toolbox mode) calls NotifyCopyrightPushedToAllImages so the spinner never hangs.
  • Dialog-launch fix (bloomImages.ts, canvasControlRegistry.ts) routes both image-button and canvas-tool launches through getWorkspaceBundleExports(), and EditingView.cs adds URL-decode/path normalisation (BL-16446) before the filename reaches PalasoImage.

Important Files Changed

Filename Overview
DistFiles/localization/en/BloomMediumPriority.xlf Adds 5 new localizable strings for the metadata chooser, push-to-all button, and status labels; note that the two now-unused strings in en/Bloom.xlf (from the deleted MessageBox code) are not marked obsolete.
src/BloomBrowserUI/bookEdit/copyrightAndLicense/CopyrightAndLicenseDialog.tsx Integrates MetadataChooser, adds push-to-all-images state machine driven by a WebSocket event, and guards the OK button during in-flight pushes; overall logic is sound.
src/BloomBrowserUI/bookEdit/copyrightAndLicense/MetadataChooser.tsx New component that progressively gathers and displays reusable metadata options; per-image errors are handled individually, but the list-endpoint fetch has an existing unhandled rejection (already flagged in a previous review comment).
src/BloomBrowserUI/bookEdit/copyrightAndLicense/metadataReuseUtils.ts New utility file with computePackageKey and getLicenseShorthand; logic is clean and consistent with the existing LicenseBadge.tsx patterns.
src/BloomExe/web/controllers/CopyrightAndLicenseApi.cs Adds two read-only endpoints for the metadata chooser and rewires push-to-all to use a WebSocket notification instead of a blocking MessageBox; error paths all call NotifyCopyrightPushedToAllImages so the spinner never hangs.
src/BloomExe/Edit/EditingView.cs Removes the old MessageBox prompt, adds URL-decode/path-only normalisation for the image filename (BL-16446 fix), and delegates 'copy to all' to the new WebSocket-notification flow.
src/BloomExe/Edit/EditingModel.cs Adds WebSocket notification method and constants for signalling 'push complete' to the still-open dialog; straightforward and well-commented.
src/BloomExe/web/controllers/ImageApi.cs Extracts a new static helper GetCreditableImageFileNamesInBook from the existing filtering logic so CopyrightAndLicenseApi can reuse it without an ImageApi instance.
src/BloomBrowserUI/bookEdit/js/bloomImages.ts Switches dialog launch to getWorkspaceBundleExports().showCopyrightAndLicenseDialog so page-iframe reloads no longer tear down the dialog.
src/BloomBrowserUI/bookEdit/toolbox/canvas/canvasControlRegistry.ts Same workspace-bundle launch fix as bloomImages.ts, applied to the canvas-tool copyright menu action.

Reviews (3): Last reviewed commit: "Fix hanging spinner on "Add to all image..." | Re-trigger Greptile

hatton and others added 2 commits June 19, 2026 09:13
…els)

The gather useEffect ran once on mount and baked localized labels into each
package's summary/secondaryLabel. But useL10n returns the English fallback
synchronously and the localized string only on a later render, so those
display strings were stuck in English (non-CC license shorthands and the
"Copyright and license from this book" label).

Store only raw data in each package (plus an isFromThisBook flag) and compute
the summary and the book label at render time, where the labels are always the
current, localized ones. The gather effect no longer captures any label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vy5zgbKXxtYoMeaUxWBhA8
When the Copyright & License dialog is launched from the Palaso image
toolbox, the POST handler early-returns before reaching the SaveThen
block that calls NotifyCopyrightPushedToAllImages(). The "Add this info
to all images" button is still visible in that case, so clicking it left
the dialog spinner stuck on "Working…" forever. Now fire the
notification in the toolbox early-return path to clear the spinner.

Also disable the OK button while a push is in flight (so the dialog
can't unmount before the "pushedToAllImages" event arrives) and add a
clarifying comment about path traversal in HandleImageMetadataForFile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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