pax 250b144806 Decouple bookmark folders from library folders, add move-aware save + submenu pickers everywhere
Bookmark folders and library folders used to share identity through
_db.get_folders() — the same string was both a row in favorite_folders
and a directory under saved_dir. They look like one concept but they're
two stores, and the cross-bleed produced a duplicate-on-move bug and
made "Save to Library" silently re-file the bookmark too.

Now they're independent name spaces:
  - library_folders() in core.config reads filesystem subdirs of
    saved_dir; the source of truth for every Save-to-Library menu
  - find_library_files(post_id) walks the library shallowly and is the
    new "is this saved?" / delete primitive
  - bookmark folders stay DB-backed and are only used for bookmark
    organization (filter combo, Move to Folder)
  - delete_from_library no longer takes a folder hint — walks every
    library folder by post id and deletes every match (also cleans up
    duplicates left by the old save-to-folder copy bug)
  - _save_to_library is move-aware: if the post is already in another
    library folder, atomic Path.rename() into the destination instead
    of re-copying from cache (the duplicate bug fix)
  - bookmark "Move to Folder" no longer also calls _copy_to_library;
    Save to Library no longer also calls move_bookmark_to_folder
  - settings export/import unchanged; favorite_folders table preserved
    so no migration

UI additions:
  - Library tab right-click: Move to Folder submenu (single + multi),
    uses Path.rename for atomic moves
  - Bookmarks tab: − Folder button next to + Folder for deleting the
    selected bookmark folder (DB-only, library filesystem untouched)
  - Browse tab right-click: "Bookmark" replaced with "Bookmark as"
    submenu when not yet bookmarked (Unfiled / folders / + New); flat
    "Remove Bookmark" when already bookmarked
  - Embedded preview Bookmark button: same submenu shape via new
    bookmark_to_folder signal + set_bookmark_folders_callback
  - Popout Bookmark button: same shape — works in both browse and
    bookmarks tab modes
  - Popout Save button: Save-to-Library submenu via new save_to_folder
    + unsave_requested signals (drops save_toggle_requested + the
    _save_toggle_from_popout indirection)
  - Popout in library mode: Save button stays visible as Unsave; the
    rest of the toolbar (Bookmark / BL Tag / BL Post) is hidden

State plumbing:
  - _update_fullscreen_state mirrors the embedded preview's
    _is_bookmarked / _is_saved instead of re-querying DB+filesystem,
    eliminating the popout state drift during async bookmark adds
  - Library tab Save button reads "Unsave" the entire time; Save
    button width bumped 60→75 so the label doesn't clip on tight themes
  - Embedded preview tracks _is_bookmarked alongside _is_saved so the
    new Bookmark-as submenu can flip to a flat unbookmark when active

Naming:
  - "Unsorted" renamed to "Unfiled" everywhere user-facing — library
    Unfiled and bookmarks Unfiled now share one label. Internal
    comparison in library.py:_scan_files updated to match the combo.
2026-04-07 19:50:39 -05:00
..