From af9b68273c1dd34e29e575b0340c4e52366794be Mon Sep 17 00:00:00 2001 From: pax Date: Thu, 9 Apr 2026 19:21:57 -0500 Subject: [PATCH] bookmarks: await save_post_file (now async) via run_on_app_loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bookmark save sites updated for save_post_file's sync→async signature change: _save_bookmark_to_library: wraps the save in an async closure and schedules via run_on_app_loop (already imported for the thumbnail download path). Fire-and-forget; the source file is already cached so the save is near-instant. Save As action: same async wrapper pattern. The dialog runs synchronously (user picks destination), then the actual file copy is scheduled on the async loop. Neither site passes a category_fetcher — bookmarks don't have a direct reference to the active BooruClient. The save flow's ensure_categories check in library_save.py short-circuits (the fetcher is None), so template rendering uses whatever categories are already on the post object. For bookmark→library saves, the user typically hasn't clicked the post in the browse grid, so categories may be empty — the template falls back to %id% for category tokens, same as before. Full categorization on the bookmark save path is a future enhancement (would require passing the client through from main_window). --- booru_viewer/gui/bookmarks.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/booru_viewer/gui/bookmarks.py b/booru_viewer/gui/bookmarks.py index 6a90cde..c5b1b15 100644 --- a/booru_viewer/gui/bookmarks.py +++ b/booru_viewer/gui/bookmarks.py @@ -286,10 +286,14 @@ class BookmarksView(QWidget): return src = Path(fav.cached_path) post = self._bookmark_to_post(fav) - try: - save_post_file(src, post, dest_dir, self._db) - except Exception as e: - log.warning(f"Bookmark→library save #{fav.post_id} failed: {e}") + + async def _do(): + try: + await save_post_file(src, post, dest_dir, self._db) + except Exception as e: + log.warning(f"Bookmark→library save #{fav.post_id} failed: {e}") + + run_on_app_loop(_do()) def _copy_to_library_unsorted(self, fav: Bookmark) -> None: """Copy a bookmarked image to the unsorted library folder.""" @@ -404,13 +408,17 @@ class BookmarksView(QWidget): dest = save_file(self, "Save Image", default_name, f"Images (*{src.suffix})") if dest: dest_path = Path(dest) - try: - save_post_file( - src, post, dest_path.parent, self._db, - explicit_name=dest_path.name, - ) - except Exception as e: - log.warning(f"Bookmark Save As #{fav.post_id} failed: {e}") + + async def _do_save_as(): + try: + await save_post_file( + src, post, dest_path.parent, self._db, + explicit_name=dest_path.name, + ) + except Exception as e: + log.warning(f"Bookmark Save As #{fav.post_id} failed: {e}") + + run_on_app_loop(_do_save_as()) elif action == unsave_lib: from ..core.cache import delete_from_library # Pass db so templated filenames are matched and the meta