Stirling-PDF icon indicating copy to clipboard operation
Stirling-PDF copied to clipboard

feature(bookmark-editor): add undo, redo and remove-all button

Open lukasstorck opened this issue 4 months ago • 5 comments

Description of Changes

Updated description of changes

  • add undo button to recover the previous bookmark state

    • on every change the previous state is saved to previousBookmarks
    • if a previous state is available it can be loaded with a button at the bottom of the editor or by pressing ctrl+z, otherwise the button is disabled
    • ~note: only the immediately previous state is saved not a full history~
  • add clear all button to remove all bookmarks from the editor preview

    • when importing a PDF with many bookmarks it can be tedious to remove them one by one
    • clearing all bookmarks can also be recovered with the undo button
  • suggestions for other button placements are very welcome, I had no better idea :D

  • both buttons have tooltips, which currently use the Stirling-PDF implementation ~(not Bootstrap like some other tooltips in the bookmark editor, see #4136)~


Checklist

General

Documentation

UI Changes (if applicable)

  • [x] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) Bookmark Editor with undo and clear all button with Redo button: Bookmark Editor with undo, redo and clear all button

Testing (if applicable)

  • [x] I have tested my changes locally. Refer to the Testing Guide for more details.

lukasstorck avatar Aug 11 '25 22:08 lukasstorck

🚀 Translation Verification Summary

🔄 Reference Branch: pr-branch-messages_en_GB.properties

📃 File Check: messages_ar_AR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_az_AZ.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_bg_BG.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_bo_CN.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_ca_CA.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_cs_CZ.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_da_DK.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_de_DE.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_el_GR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_en_GB.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_en_US.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_es_ES.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_eu_ES.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_fa_IR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_fr_FR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_ga_IE.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_hi_IN.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_hr_HR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_hu_HU.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_id_ID.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_it_IT.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_ja_JP.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_ko_KR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_ml_IN.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_nl_NL.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_no_NB.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_pl_PL.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_pt_BR.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_pt_PT.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

📃 File Check: messages_ro_RO.properties

  1. Test Status:Passed
  2. Test Status:Passed
  3. Test Status:Passed

✅ Overall Check Status: Success

Thanks @lukasstorck for your help in keeping the translations up to date.

stirlingbot[bot] avatar Aug 11 '25 22:08 stirlingbot[bot]

tldr: The check for the translation strings fails, as there are modified files that do not have all strings from the reference file (messages_en_GB.properties). This only fails here and not previously, as previous commits only modified the en_GB file and did not propagate the additions to the other languages.

There are two commits (1, 2) from yesterday and today, that add translation strings, but they were only added to the British English file. I am guessing, that the translation file check only checks the modified files and so the error for missing strings for the other languages is not shown.

I assumed, that we are supposed to propagate new translation string to the other languages files (I use for f in app/core/src/main/resources/messages_*; do python3 .github/scripts/check_language_properties.py --reference-file app/core/src/main/resources/messages_en_GB.properties --branch "" --check-file "$f"; done). But maybe I misunderstood the guideline.

I can add the missing strings in this PR, but maybe you want to add them in a separate PR, as it does not belong here.

lukasstorck avatar Sep 29 '25 20:09 lukasstorck

Merged https://github.com/Stirling-Tools/Stirling-PDF/pull/4542 To help with translation string issue Thanjs

Frooodle avatar Sep 29 '25 21:09 Frooodle

I noticed, that the "undo memory" does not capture changes to the title and page fields directly, because these do not trigger the saveBookmarkState() variable update. This might confuse some users that want to reverse a typo or reverse a page entry edit. Currently only structure edits (new bookmark entry as sibling or child) are reflected, which now (due to serialization to json) can include edits to title and page, when they were made before the structure change.

Then again, users might also expect an update history (multiple undos and redos), which could be done by saving multiple instances of the bookmark state, but this is ugly and a better solution would be to track the incremental changes with something like JSON-Patch (e.g. fast-json-patch).

lukasstorck avatar Oct 06 '25 13:10 lukasstorck

New Changes (add redo, full forward and backward history of changes)

  • keep track of full history of changes in forward and backward direction
    • use JSON patches to save incremental changes in two stacks
    • load new fast-json-patch JS module (MIT license) that provides JSON patch functionality
    • undoStack stores incremental patches that can be applied to get from the current state to a previous state
    • redoStack stores incremental patches that reverse previous undo actions (reapply actions), is reset when new action (like manually adding a bookmark) is taken, as this create as "new future path"
  • change undo button implementation
    1. get latest undo patch from stack (patch that reverses the last action)
    2. apply patch to bookmark state
    3. push inverted patch to the redo stack
  • add redo button and ctrl+y (meta+y) shortcut
    1. get latest redo patch from stack (patch that redoes the last undo step)
    2. apply patch to bookmark state
    3. push inverted patch to the undo stack
  • add translation tags for redo button tooltip
  • track all changes
    • previously only structural changes were tracked for edit history
    • now also changes to the title and page number of each bookmark are tracked
    • implemented by listening to all change events under the bookmarksContainer

Updated Description of Changes

  • manage bookmark edit history
    • all changes (bookmark structure, title and page number fields) are captured as JSON patches
    • two stacks are maintained for forward and backwards history
    • patches can be applied with undo and redo functions
    • fast-json-patch is used to generate and apply the patches
  • add undo and redo buttons
    • apply JSON patches if available (when changes were made or can be redone after previous undo)
    • also add keyboard shortcuts with ctrl+z and ctrl+y (for macOS: meta+z and meta+y)
  • add clear all button to remove all bookmarks from the editor preview
    • when importing a PDF with many bookmarks it can be tedious to remove them one by one
    • clearing all bookmarks can also be recovered with the undo button

UI Changes (if applicable)

  • [x] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) Bookmark Editor with undo, redo and clear all button

lukasstorck avatar Oct 08 '25 19:10 lukasstorck