k
This commit is contained in:
@@ -47,6 +47,60 @@ import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _normalize_detail_tags(tags: Any) -> List[str]:
|
||||
if not tags:
|
||||
return []
|
||||
if isinstance(tags, str):
|
||||
source = [part.strip() for part in tags.split(",")]
|
||||
elif isinstance(tags, (list, tuple, set)):
|
||||
source = [str(part or "").strip() for part in tags]
|
||||
else:
|
||||
source = [str(tags).strip()]
|
||||
|
||||
seen: set[str] = set()
|
||||
normalized: List[str] = []
|
||||
for tag in source:
|
||||
text = str(tag or "").strip()
|
||||
if not text:
|
||||
continue
|
||||
key = text.casefold()
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
normalized.append(text)
|
||||
return normalized
|
||||
|
||||
|
||||
def _partition_detail_tags(tags: Any) -> tuple[List[str], List[str]]:
|
||||
normalized = _normalize_detail_tags(tags)
|
||||
namespace_tags: List[str] = []
|
||||
freeform_tags: List[str] = []
|
||||
for tag in normalized:
|
||||
namespace, sep, value = str(tag).partition(":")
|
||||
if sep and namespace.strip() and value.strip():
|
||||
namespace_tags.append(tag)
|
||||
else:
|
||||
freeform_tags.append(tag)
|
||||
|
||||
namespace_tags.sort(
|
||||
key=lambda value: (
|
||||
str(value).partition(":")[0].casefold(),
|
||||
str(value).partition(":")[2].casefold(),
|
||||
str(value).casefold(),
|
||||
)
|
||||
)
|
||||
freeform_tags.sort(key=lambda value: str(value).casefold())
|
||||
return namespace_tags, freeform_tags
|
||||
|
||||
|
||||
def _chunk_detail_tags(tags: List[str], columns: int) -> List[List[str]]:
|
||||
column_count = max(1, int(columns or 1))
|
||||
rows: List[List[str]] = []
|
||||
for index in range(0, len(tags), column_count):
|
||||
rows.append(tags[index:index + column_count])
|
||||
return rows
|
||||
|
||||
|
||||
_RESULT_TABLE_ROW_STYLE_LOOP: List[tuple[str, str]] = [
|
||||
("#ff0000", "#8f00ff"),
|
||||
("#ffa500", "#800080"),
|
||||
@@ -2213,7 +2267,6 @@ class ItemDetailView(Table):
|
||||
from rich.table import Table as RichTable
|
||||
from rich.panel import Panel
|
||||
from rich.console import Group
|
||||
from rich.columns import Columns
|
||||
from rich.text import Text
|
||||
|
||||
# 1. Create Detail Grid (matching rich_display.py style)
|
||||
@@ -2236,6 +2289,28 @@ class ItemDetailView(Table):
|
||||
tag_text.append(raw, style="green")
|
||||
return tag_text
|
||||
|
||||
def _build_tag_renderable(tags: Any) -> Optional[Any]:
|
||||
namespace_tags, freeform_tags = _partition_detail_tags(tags)
|
||||
if not namespace_tags and not freeform_tags:
|
||||
return None
|
||||
|
||||
renderables: List[Any] = []
|
||||
for tag in namespace_tags:
|
||||
renderables.append(_render_tag_text(tag))
|
||||
|
||||
if freeform_tags:
|
||||
freeform_grid = RichTable.grid(expand=True, padding=(0, 2))
|
||||
for _ in range(3):
|
||||
freeform_grid.add_column(ratio=1)
|
||||
for row_values in _chunk_detail_tags(freeform_tags, 3):
|
||||
cells = [_render_tag_text(tag) for tag in row_values]
|
||||
while len(cells) < 3:
|
||||
cells.append(Text(""))
|
||||
freeform_grid.add_row(*cells)
|
||||
renderables.append(freeform_grid)
|
||||
|
||||
return Group(*renderables)
|
||||
|
||||
# Canonical display order for metadata
|
||||
order = ["Title", "Hash", "Store", "Path", "Ext", "Size", "Duration", "Url", "Relations"]
|
||||
|
||||
@@ -2280,13 +2355,11 @@ class ItemDetailView(Table):
|
||||
# Tags Summary
|
||||
tags = self.item_metadata.get("Tags") or self.item_metadata.get("tags") or self.item_metadata.get("tag")
|
||||
if not self.exclude_tags and tags and isinstance(tags, (list, str)):
|
||||
if isinstance(tags, str):
|
||||
tags = [t.strip() for t in tags.split(",") if t.strip()]
|
||||
tags_sorted = sorted(map(str, tags))
|
||||
tag_cols = Columns([_render_tag_text(t) for t in tags_sorted], equal=True, expand=True)
|
||||
details_table.add_row("", "") # Spacer
|
||||
details_table.add_row("Tags:", tag_cols)
|
||||
has_details = True
|
||||
tag_renderable = _build_tag_renderable(tags)
|
||||
if tag_renderable is not None:
|
||||
details_table.add_row("", "")
|
||||
details_table.add_row("Tags:", tag_renderable)
|
||||
has_details = True
|
||||
|
||||
# 2. Get the standard table render (if there are rows or a specific title)
|
||||
original_title = self.title
|
||||
|
||||
Reference in New Issue
Block a user