import { consume } from "@lit/context"; import { ClientConsumer } from "../ClientConsumer"; import { currentUserTreeContext, currentUserTreeSetterContext } from "../../ClientContext"; import { TreeItem } from "@labir/server"; import { customElement, property, state } from "lit/decorators.js"; import { css, html, nothing, PropertyValues, TemplateResult } from "lit"; @customElement("server-breadcrumb") export class ServerBreadcrumb extends ClientConsumer { @consume({ context: currentUserTreeContext, subscribe: true }) protected tree: TreeItem[] = []; @consume({ context: currentUserTreeSetterContext, subscribe: true }) protected treeSetter?: (tree: TreeItem[]) => void = undefined; @property({ type: String, reflect: true }) public current!: string; @state() protected folders: TreeItem[] = []; connectedCallback(): void { super.connectedCallback(); if ( this.tree.length === 0 ) { this.fetchTree(); } this.client?.auth.onIdentity.set(this.UUID, async () => { this.treeSetter?.( [] ); // await this.fetchTree(); this.folders = this.getCurrentFolderParents(); // this.requestUpdate(); }); } protected update(changedProperties: PropertyValues): void { super.update(changedProperties); if ( changedProperties.has("current") ) { this.folders = this.getCurrentFolderParents(); this.requestUpdate(); console.log( "Updated folders:", this.folders, this.current, this.tree ); } } protected async fetchTree(): Promise { if ( !this.isClientConnected || !this.client) { return; } const tree = this.client.routes.get.currentUserTree(); const treeResult = await tree.execute(); if ( treeResult.success ) { this.treeSetter?.(treeResult.data.tree); this.folders = this.getCurrentFolderParents(); } else { console.error("Failed to fetch user tree:", treeResult.message); } } protected renderItem( name: string, className: string, hasArrow: boolean = true, icon?: TemplateResult, onClick?: () => void ): TemplateResult { return html` ${hasArrow ? html`/` : nothing} `; } protected renderServerName(): TemplateResult { return this.renderItem( this.serverInfo?.name ?? "Server", "server", false, html` ` ); } protected renderUserName(): unknown { if ( this.identity === undefined ) { return nothing; } return this.renderItem( this.identity.meta.name, "user", true, html` ` ); } protected getCurrentFolderParents(): TreeItem[] { if (!this.current || !this.tree || this.tree.length === 0) { return []; } // Helper to recursively search for the path and collect the full path (parents + current) function findPath( nodes: TreeItem[], targetPath: string, parents: TreeItem[] = [] ): TreeItem[] | null { for (const node of nodes) { const newParents = [...parents, node]; if (node.path === targetPath) { return newParents; } if (node.subfolders && node.subfolders.length > 0) { const found = findPath(node.subfolders, targetPath, newParents); if (found) { return found; } } } return null; } const path = findPath(this.tree, this.current); return path ?? []; } public static styles = css` :host { display: block; width: 100%; height: 100%; box-sizing: border-box; } .server-breadcrumb { display: flex; flex-wrap: wrap; gap: calc( var(--thermal-gap) * 0.5 ); align-items: center; font-size: calc( var(--thermal-fs) * 0.8 ); color: var(--thermal-slate-dark); font-family: sans-serif; } button { display: inline-block; padding: 0; margin: 0; background: transparent; border: none; color: var(--thermal-slate-dark); font-size: calc( var(--thermal-fs) * 0.8 ); font-family: sans-serif !important; transition: color 0.2s ease-in-out; svg { display: inline-block; transform: translateY(0.1em); } } svg { width: 1em; height: 1em; line-height: 1em; } .server { color: var(--thermal-slate); } .user { color: var(--thermal-slate); } .folder { color: var(--thermal-slate); cursor: pointer; &:hover { color: var(--thermal-primary); } } .current { color: var(--thermal-foreground); } .slash { color: var(--thermal-slate); } `; protected render(): unknown { if ( ! this.isClientConnected || ! this.isLoggedIn ) { return nothing; } const folders = this.folders.length === 0 ? this.renderItem("Načítám...", "folder", true) : this.folders.map((folder, index) => { const className = index === this.folders.length - 1 ? "folder current" : "folder"; return this.renderItem( folder.name ?? "/", className, true, html` `, () => { this.log(folder, index); // this.client?.routes.navigate(folder.path); } ); }); return html`
${this.renderServerName()} ${this.renderUserName()} ${folders}
`; } }