fix: multi owner

This commit is contained in:
tao.chen
2026-08-12 18:58:18 +08:00
parent 495018de34
commit 8abe505d17
3 changed files with 40 additions and 26 deletions
@@ -178,25 +178,29 @@ export function ScriptExplorer({
</div>
) : (
<>
{memberScriptGroups.map((group) => (
<WorkspaceTreeGroup
key={group.user?.user_id ?? "anon"}
title={`${group.user?.display_name}`}
scripts={group.scripts}
directories={group.directories}
selectedId={selectedId}
onSelect={onSelect}
onContextMenu={
group.user?.user_id === user?.user_id
? onContextMenu
: undefined
}
readOnly={group.user?.user_id !== user?.user_id}
expandedPaths={expandedPaths}
onToggle={onToggle}
loadingChildrenPaths={loadingChildrenPaths}
/>
))}
{memberScriptGroups.map((group) => {
const ownerKey = group.user?.user_id ?? "anon";
return (
<WorkspaceTreeGroup
key={ownerKey}
groupKey={`__group__${ownerKey}`}
title={`${group.user?.display_name}`}
scripts={group.scripts}
directories={group.directories}
selectedId={selectedId}
onSelect={onSelect}
onContextMenu={
group.user?.user_id === user?.user_id
? onContextMenu
: undefined
}
readOnly={group.user?.user_id !== user?.user_id}
expandedPaths={expandedPaths}
onToggle={onToggle}
loadingChildrenPaths={loadingChildrenPaths}
/>
);
})}
{filteredScripts.length === 0 && (
<div className="tree-empty">
<span className="tree-empty__icon">
@@ -1,4 +1,4 @@
import { type MouseEvent as ReactMouseEvent } from "react";
import { type MouseEvent as ReactMouseEvent, useEffect } from "react";
import Icon from "../../components/common/Icon";
import type {
@@ -23,12 +23,14 @@ type WorkspaceTreeProps = {
target: WorkspaceTreeTarget,
) => void;
readOnly?: boolean;
// 唯一标识此 group(通常 `__group__<owner_user_id>`),让多个 owner 的 group 各自独立展开。
groupKey: string;
expandedPaths: Set<string>;
onToggle: (path: string) => void;
loadingChildrenPaths: Set<string>;
};
type WorkspaceTreeItemsProps = Omit<WorkspaceTreeProps, "title" | "readOnly"> & {
type WorkspaceTreeItemsProps = Omit<WorkspaceTreeProps, "title" | "readOnly" | "groupKey"> & {
path: string;
depth: number;
};
@@ -65,19 +67,27 @@ export function WorkspaceTreeGroup({
onSelect,
onContextMenu,
readOnly = false,
groupKey,
expandedPaths,
onToggle,
loadingChildrenPaths,
}: WorkspaceTreeProps) {
const open = expandedPaths.has("");
const childrenLoading = loadingChildrenPaths.has("");
const open = expandedPaths.has(groupKey);
// 首次挂载自动展开(保留原本 useState(true) 的默认展开行为)。
// toggleExpanded 内识别 `__group__` 前缀,不会触发 loadChildren。
useEffect(() => {
if (!expandedPaths.has(groupKey)) {
void onToggle(groupKey);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [groupKey]);
return (
<div className="tree-group">
<button
className={`tree-group__title${open ? " is-open" : ""}`}
type="button"
aria-expanded={open}
onClick={() => onToggle("")}
onClick={() => onToggle(groupKey)}
onContextMenu={onContextMenu
? (event) => onContextMenu(event, { kind: "root", path: "" })
: undefined}
@@ -86,7 +96,6 @@ export function WorkspaceTreeGroup({
<Icon name="folder" size={17} />
<span>{title}</span>
<em>{scripts.length}</em>
{childrenLoading && <span className="loading-spinner" />}
</button>
{open && (
<div className="tree-group__items">
@@ -293,7 +293,8 @@ export const useScriptWorkspaceStore = create<State>((set, get) => {
next.delete(path);
} else {
next.add(path);
if (!state.loadedChildPaths.has(path)) {
// group key (`__group__<owner_id>`) 不是 workspace 路径,不调 loadChildren
if (!path.startsWith("__group__") && !state.loadedChildPaths.has(path)) {
void get().loadChildren(path);
}
}