mirror of
https://github.com/irislib/iris-messenger.git
synced 2024-10-18 06:03:22 +00:00
.
This commit is contained in:
parent
e409d244d9
commit
3642f285cf
@ -1,63 +1,107 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { ChevronRightIcon } from '@heroicons/react/20/solid';
|
||||||
|
|
||||||
import Node from '@/state/Node';
|
import Show from '@/components/helpers/Show.tsx';
|
||||||
|
import Node, { DIR_VALUE } from '@/state/Node';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
node: Node;
|
node: Node;
|
||||||
|
value?: any;
|
||||||
level?: number;
|
level?: number;
|
||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
parentCounter?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ExplorerNode({ node, level = 0, expanded = false, name }: Props) {
|
const VALUE_TRUNCATE_LENGTH = 50;
|
||||||
const [children, setChildren] = useState<{ [key: string]: Node }>({});
|
|
||||||
|
export default function ExplorerNode({
|
||||||
|
node,
|
||||||
|
value = DIR_VALUE,
|
||||||
|
level = 0,
|
||||||
|
expanded = false,
|
||||||
|
name,
|
||||||
|
parentCounter = 0,
|
||||||
|
}: Props) {
|
||||||
|
const [children, setChildren] = useState<{ [key: string]: { node: Node; value: any } }>({});
|
||||||
const [isOpen, setIsOpen] = useState(expanded);
|
const [isOpen, setIsOpen] = useState(expanded);
|
||||||
|
const [showMore, setShowMore] = useState(false);
|
||||||
|
|
||||||
|
const isDirectory = value === DIR_VALUE;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
node.map((_value, key) => {
|
if (!isDirectory) return;
|
||||||
|
return node.map((value, key) => {
|
||||||
if (!children[key]) {
|
if (!children[key]) {
|
||||||
setChildren((prev) => {
|
const childName = key.split('/').pop()!;
|
||||||
const childName = key.split('/').pop()!;
|
setChildren((prev) => ({
|
||||||
return { ...prev, [key]: node.get(childName) };
|
...prev,
|
||||||
});
|
[key]: { node: node.get(childName), value },
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [node.id]);
|
}, [node.id, value]);
|
||||||
|
|
||||||
const toggleOpen = () => {
|
const toggleOpen = () => setIsOpen(!isOpen);
|
||||||
setIsOpen(!isOpen);
|
const rowColor = parentCounter % 2 === 0 ? 'bg-gray-800' : 'bg-gray-700';
|
||||||
};
|
|
||||||
|
|
||||||
const isEven = level % 2 === 0;
|
|
||||||
const displayName = name || node.id.split('/').pop()!;
|
const displayName = name || node.id.split('/').pop()!;
|
||||||
|
|
||||||
|
const renderValue = (value) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return (
|
||||||
|
<span className="text-xs text-blue-400">
|
||||||
|
{value.length > VALUE_TRUNCATE_LENGTH && (
|
||||||
|
<span
|
||||||
|
className="text-xs text-blue-200 cursor-pointer"
|
||||||
|
onClick={() => setShowMore(!showMore)}
|
||||||
|
>
|
||||||
|
Show {showMore ? 'less' : 'more'}{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
"
|
||||||
|
{showMore
|
||||||
|
? value
|
||||||
|
: value.length > VALUE_TRUNCATE_LENGTH
|
||||||
|
? `${value.substring(0, VALUE_TRUNCATE_LENGTH)}...`
|
||||||
|
: value}
|
||||||
|
"
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <span className="text-xs text-green-400">{JSON.stringify(value)}</span>;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`relative ${isEven ? 'bg-gray-800' : 'bg-gray-700'}`}>
|
<div className={`relative w-full ${rowColor}`}>
|
||||||
<div className="flex items-center cursor-pointer text-white" onClick={toggleOpen}>
|
<div
|
||||||
<div className={`transition ${isOpen ? 'transform rotate-90' : ''}`}>
|
className={`flex items-center text-white ${isDirectory ? 'cursor-pointer' : null}`}
|
||||||
<svg
|
onClick={toggleOpen}
|
||||||
className="w-4 h-4"
|
style={{ paddingLeft: `${level * 15}px` }}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
>
|
||||||
fill="none"
|
<Show when={isDirectory}>
|
||||||
viewBox="0 0 24 24"
|
<ChevronRightIcon
|
||||||
stroke="currentColor"
|
className={`w-4 h-4 transition ${isOpen ? 'transform rotate-90' : ''}`}
|
||||||
aria-hidden="true"
|
/>
|
||||||
>
|
</Show>
|
||||||
<path
|
<span className="ml-2 w-1/3 truncate">{displayName}</span>
|
||||||
strokeLinecap="round"
|
<Show when={!isDirectory}>
|
||||||
strokeLinejoin="round"
|
<div className="ml-auto w-1/2">{renderValue(value)}</div>
|
||||||
strokeWidth="2"
|
</Show>
|
||||||
d="M9 5l7 7-7 7"
|
</div>
|
||||||
></path>
|
{isOpen ? (
|
||||||
</svg>
|
<div>
|
||||||
|
{Object.values(children).map((child, index) => (
|
||||||
|
<ExplorerNode
|
||||||
|
key={node.id + child.node.id}
|
||||||
|
node={child.node}
|
||||||
|
level={level + 1}
|
||||||
|
expanded={false}
|
||||||
|
value={child.value}
|
||||||
|
parentCounter={parentCounter + index + 1}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
<span className="ml-2">{displayName}</span>
|
) : null}
|
||||||
</div>
|
|
||||||
<div className={`ml-6 ${isOpen ? 'block' : 'hidden'}`}>
|
|
||||||
{Object.values(children).map((child) => (
|
|
||||||
<ExplorerNode key={node.id + child.id} node={child} level={level + 1} expanded={false} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user