Store tag categories in bookmarks, tag click switches to Browse

- Bookmarks DB now stores tag_categories as JSON
- Migration adds column to existing favorites table
- Bookmark info panel uses stored categories directly
- Falls back to library_meta if bookmark has no categories
- Tag click in info panel: clears preview, switches to Browse, searches
This commit is contained in:
pax 2026-04-05 17:09:01 -05:00
parent 87c42f806e
commit d2aae5cd82
2 changed files with 25 additions and 7 deletions

View File

@ -134,6 +134,7 @@ class Bookmark:
cached_path: str | None cached_path: str | None
folder: str | None folder: str | None
bookmarked_at: str bookmarked_at: str
tag_categories: dict = field(default_factory=dict)
# Back-compat alias — will be removed in a future version. # Back-compat alias — will be removed in a future version.
@ -168,10 +169,14 @@ class Database:
tables = {r[0] for r in self._conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()} tables = {r[0] for r in self._conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()}
if "library_meta" in tables: if "library_meta" in tables:
cur = self._conn.execute("PRAGMA table_info(library_meta)") cur = self._conn.execute("PRAGMA table_info(library_meta)")
cols = {row[1] for row in cur.fetchall()} meta_cols = {row[1] for row in cur.fetchall()}
if "tag_categories" not in cols: if "tag_categories" not in meta_cols:
self._conn.execute("ALTER TABLE library_meta ADD COLUMN tag_categories TEXT DEFAULT ''") self._conn.execute("ALTER TABLE library_meta ADD COLUMN tag_categories TEXT DEFAULT ''")
self._conn.commit() self._conn.commit()
# Add tag_categories to favorites if missing
if "tag_categories" not in cols:
self._conn.execute("ALTER TABLE favorites ADD COLUMN tag_categories TEXT DEFAULT ''")
self._conn.commit()
def close(self) -> None: def close(self) -> None:
if self._conn: if self._conn:
@ -259,13 +264,16 @@ class Database:
source: str | None = None, source: str | None = None,
cached_path: str | None = None, cached_path: str | None = None,
folder: str | None = None, folder: str | None = None,
tag_categories: dict | None = None,
) -> Bookmark: ) -> Bookmark:
import json
now = datetime.now(timezone.utc).isoformat() now = datetime.now(timezone.utc).isoformat()
cats_json = json.dumps(tag_categories) if tag_categories else ""
cur = self.conn.execute( cur = self.conn.execute(
"INSERT OR IGNORE INTO favorites " "INSERT OR IGNORE INTO favorites "
"(site_id, post_id, file_url, preview_url, tags, rating, score, source, cached_path, folder, favorited_at) " "(site_id, post_id, file_url, preview_url, tags, rating, score, source, cached_path, folder, favorited_at, tag_categories) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(site_id, post_id, file_url, preview_url, tags, rating, score, source, cached_path, folder, now), (site_id, post_id, file_url, preview_url, tags, rating, score, source, cached_path, folder, now, cats_json),
) )
self.conn.commit() self.conn.commit()
return Bookmark( return Bookmark(
@ -352,6 +360,9 @@ class Database:
@staticmethod @staticmethod
def _row_to_bookmark(r) -> Bookmark: def _row_to_bookmark(r) -> Bookmark:
import json
cats_raw = r["tag_categories"] if "tag_categories" in r.keys() else ""
cats = json.loads(cats_raw) if cats_raw else {}
return Bookmark( return Bookmark(
id=r["id"], id=r["id"],
site_id=r["site_id"], site_id=r["site_id"],
@ -365,6 +376,7 @@ class Database:
cached_path=r["cached_path"], cached_path=r["cached_path"],
folder=r["folder"] if "folder" in r.keys() else None, folder=r["folder"] if "folder" in r.keys() else None,
bookmarked_at=r["favorited_at"], bookmarked_at=r["favorited_at"],
tag_categories=cats,
) )
# Back-compat shim # Back-compat shim

View File

@ -542,6 +542,8 @@ class BooruApp(QMainWindow):
self._grid.setFocus() self._grid.setFocus()
def _on_tag_clicked(self, tag: str) -> None: def _on_tag_clicked(self, tag: str) -> None:
self._preview.clear()
self._switch_view(0)
self._search_bar.set_text(tag) self._search_bar.set_text(tag)
self._on_search(tag) self._on_search(tag)
@ -1146,6 +1148,8 @@ class BooruApp(QMainWindow):
self._status.showMessage(f"Bookmark #{fav.post_id}") self._status.showMessage(f"Bookmark #{fav.post_id}")
# Show bookmark tags in info panel # Show bookmark tags in info panel
from ..core.api.base import Post from ..core.api.base import Post
cats = fav.tag_categories or {}
if not cats:
meta = self._db.get_library_meta(fav.post_id) meta = self._db.get_library_meta(fav.post_id)
cats = meta.get("tag_categories", {}) if meta else {} cats = meta.get("tag_categories", {}) if meta else {}
p = Post( p = Post(
@ -1672,6 +1676,7 @@ class BooruApp(QMainWindow):
file_url=post.file_url, preview_url=post.preview_url, file_url=post.file_url, preview_url=post.preview_url,
tags=post.tags, rating=post.rating, score=post.score, tags=post.tags, rating=post.rating, score=post.score,
source=post.source, cached_path=str(path), source=post.source, cached_path=str(path),
tag_categories=post.tag_categories,
) )
self._signals.bookmark_done.emit(idx, f"Bookmarked {i+1}/{len(posts)}") self._signals.bookmark_done.emit(idx, f"Bookmarked {i+1}/{len(posts)}")
except Exception as e: except Exception as e:
@ -2054,6 +2059,7 @@ class BooruApp(QMainWindow):
score=post.score, score=post.score,
source=post.source, source=post.source,
cached_path=str(path), cached_path=str(path),
tag_categories=post.tag_categories,
) )
self._signals.bookmark_done.emit(index, f"Bookmarked #{post.id}") self._signals.bookmark_done.emit(index, f"Bookmarked #{post.id}")
except Exception as e: except Exception as e: