feat: add an option to auto expand subtags in tree mode

This commit is contained in:
hchengting 2025-08-11 17:04:55 +09:00
parent c76ffb0fe4
commit a63f27fc3c
3 changed files with 17 additions and 5 deletions

View File

@ -22,6 +22,7 @@ interface Props {
const TagsSection = observer((props: Props) => { const TagsSection = observer((props: Props) => {
const t = useTranslate(); const t = useTranslate();
const [treeMode, setTreeMode] = useLocalStorage<boolean>("tag-view-as-tree", false); const [treeMode, setTreeMode] = useLocalStorage<boolean>("tag-view-as-tree", false);
const [treeAutoExpand, setTreeAutoExpand] = useLocalStorage<boolean>("tag-tree-auto-expand", false);
const renameTagDialog = useDialog(); const renameTagDialog = useDialog();
const [selectedTag, setSelectedTag] = useState<string>(""); const [selectedTag, setSelectedTag] = useState<string>("");
const tags = Object.entries(userStore.state.tagCount) const tags = Object.entries(userStore.state.tagCount)
@ -75,13 +76,17 @@ const TagsSection = observer((props: Props) => {
<span className="text-sm shrink-0">{t("common.tree-mode")}</span> <span className="text-sm shrink-0">{t("common.tree-mode")}</span>
<Switch checked={treeMode} onCheckedChange={(checked) => setTreeMode(checked)} /> <Switch checked={treeMode} onCheckedChange={(checked) => setTreeMode(checked)} />
</div> </div>
<div className="w-auto flex flex-row justify-between items-center gap-2 p-1">
<span className="text-sm shrink-0">{t("common.auto-expand")}</span>
<Switch disabled={!treeMode} checked={treeAutoExpand} onCheckedChange={(checked) => setTreeAutoExpand(checked)} />
</div>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
)} )}
</div> </div>
{tags.length > 0 ? ( {tags.length > 0 ? (
treeMode ? ( treeMode ? (
<TagTree tagAmounts={tags} /> <TagTree tagAmounts={tags} expandSubTags={!!treeAutoExpand} />
) : ( ) : (
<div className="w-full flex flex-row justify-start items-center relative flex-wrap gap-x-2 gap-y-1"> <div className="w-full flex flex-row justify-start items-center relative flex-wrap gap-x-2 gap-y-1">
{tags.map(([tag, amount]) => ( {tags.map(([tag, amount]) => (

View File

@ -13,9 +13,10 @@ interface Tag {
interface Props { interface Props {
tagAmounts: [tag: string, amount: number][]; tagAmounts: [tag: string, amount: number][];
expandSubTags: boolean;
} }
const TagTree = ({ tagAmounts: rawTagAmounts }: Props) => { const TagTree = ({ tagAmounts: rawTagAmounts, expandSubTags }: Props) => {
const [tags, setTags] = useState<Tag[]>([]); const [tags, setTags] = useState<Tag[]>([]);
useEffect(() => { useEffect(() => {
@ -74,7 +75,7 @@ const TagTree = ({ tagAmounts: rawTagAmounts }: Props) => {
return ( return (
<div className="flex flex-col justify-start items-start relative w-full h-auto flex-nowrap gap-2 mt-1"> <div className="flex flex-col justify-start items-start relative w-full h-auto flex-nowrap gap-2 mt-1">
{tags.map((t, idx) => ( {tags.map((t, idx) => (
<TagItemContainer key={t.text + "-" + idx} tag={t} /> <TagItemContainer key={t.text + "-" + idx} tag={t} expandSubTags={expandSubTags} />
))} ))}
</div> </div>
); );
@ -82,15 +83,20 @@ const TagTree = ({ tagAmounts: rawTagAmounts }: Props) => {
interface TagItemContainerProps { interface TagItemContainerProps {
tag: Tag; tag: Tag;
expandSubTags: boolean;
} }
const TagItemContainer = observer((props: TagItemContainerProps) => { const TagItemContainer = observer((props: TagItemContainerProps) => {
const { tag } = props; const { tag, expandSubTags } = props;
const tagFilters = memoFilterStore.getFiltersByFactor("tagSearch"); const tagFilters = memoFilterStore.getFiltersByFactor("tagSearch");
const isActive = tagFilters.some((f: MemoFilter) => f.value === tag.text); const isActive = tagFilters.some((f: MemoFilter) => f.value === tag.text);
const hasSubTags = tag.subTags.length > 0; const hasSubTags = tag.subTags.length > 0;
const [showSubTags, toggleSubTags] = useToggle(false); const [showSubTags, toggleSubTags] = useToggle(false);
useEffect(() => {
toggleSubTags(expandSubTags);
}, [expandSubTags]);
const handleTagClick = () => { const handleTagClick = () => {
if (isActive) { if (isActive) {
memoFilterStore.removeFilter((f: MemoFilter) => f.factor === "tagSearch" && f.value === tag.text); memoFilterStore.removeFilter((f: MemoFilter) => f.factor === "tagSearch" && f.value === tag.text);
@ -140,7 +146,7 @@ const TagItemContainer = observer((props: TagItemContainerProps) => {
}`} }`}
> >
{tag.subTags.map((st, idx) => ( {tag.subTags.map((st, idx) => (
<TagItemContainer key={st.text + "-" + idx} tag={st} /> <TagItemContainer key={st.text + "-" + idx} tag={st} expandSubTags={expandSubTags} />
))} ))}
</div> </div>
) : null} ) : null}

View File

@ -21,6 +21,7 @@
"archive": "Archive", "archive": "Archive",
"archived": "Archived", "archived": "Archived",
"attachments": "Attachments", "attachments": "Attachments",
"auto-expand": "Auto expand",
"avatar": "Avatar", "avatar": "Avatar",
"basic": "Basic", "basic": "Basic",
"beta": "Beta", "beta": "Beta",