Add focus button to TreeNode and adjust Outline component state

This commit is contained in:
2025-10-08 09:10:00 +05:30
parent 4764585536
commit a55d25e55b
2 changed files with 89 additions and 14 deletions

View File

@@ -9,6 +9,7 @@ import {
AddIcon, AddIcon,
KebebIcon, KebebIcon,
CollapseAllIcon, CollapseAllIcon,
FocusIcon,
} from "../../../components/icons/ExportCommonIcons"; } from "../../../components/icons/ExportCommonIcons";
import RenameInput from "../../../components/ui/inputs/RenameInput"; import RenameInput from "../../../components/ui/inputs/RenameInput";
import { useSceneContext } from "../../scene/sceneContext"; import { useSceneContext } from "../../scene/sceneContext";
@@ -18,6 +19,7 @@ import useAssetResponseHandler from "../../collaboration/responseHandler/useAsse
import { getUserData } from "../../../functions/getUserData"; import { getUserData } from "../../../functions/getUserData";
import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import clsx from "clsx"; import clsx from "clsx";
import { useContextActionStore } from "../../../store/builder/store";
interface DragState { interface DragState {
draggedItem: AssetGroupChild | null; draggedItem: AssetGroupChild | null;
@@ -121,7 +123,10 @@ const TreeNode = ({
const shouldShowHighlight = isDropTarget(); const shouldShowHighlight = isDropTarget();
return ( return (
<div key={itemId} className={`tree-node ${shouldShowHighlight ? "drop-target-highlight" : ""}`}> <div
key={itemId}
className={`tree-node ${shouldShowHighlight ? "drop-target-highlight" : ""}`}
>
<div <div
className={clsx("tree-node-content", { className={clsx("tree-node-content", {
locked: isLocked, locked: isLocked,
@@ -163,6 +168,15 @@ const TreeNode = ({
> >
<EyeIcon isClosed={!isVisible} /> <EyeIcon isClosed={!isVisible} />
</button> </button>
<button
className="control-button"
title={isLocked ? "Locked" : "Unlocked"}
onClick={(e) => {
handleOptionClick(e, "focus");
}}
>
<FocusIcon />
</button>
<button <button
className="control-button" className="control-button"
title={isLocked ? "Locked" : "Unlocked"} title={isLocked ? "Locked" : "Unlocked"}
@@ -217,7 +231,8 @@ const TreeNode = ({
// Main Component // Main Component
export const Outline = () => { export const Outline = () => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(true);
const { setContextAction } = useContextActionStore();
const lastSelectedRef = useRef<{ item: AssetGroupChild; index: number } | null>(null); const lastSelectedRef = useRef<{ item: AssetGroupChild; index: number } | null>(null);
const dragStateRef = useRef<DragState>({ const dragStateRef = useRef<DragState>({
draggedItem: null, draggedItem: null,
@@ -227,8 +242,25 @@ export const Outline = () => {
}); });
const [_, forceUpdate] = useState({}); const [_, forceUpdate] = useState({});
const { scene, assetGroupStore, assetStore, versionStore, undoRedo3DStore } = useSceneContext(); const { scene, assetGroupStore, assetStore, versionStore, undoRedo3DStore } = useSceneContext();
const { addSelectedAsset, clearSelectedAssets, getAssetById, peekToggleVisibility, peekToggleLock, toggleSelectedAsset, selectedAssets } = assetStore(); const {
const { groupHierarchy, isGroup, getGroupsContainingAsset, getFlatGroupChildren, setGroupExpanded, addChildToGroup, removeChildFromGroup, getGroupsContainingGroup } = assetGroupStore(); addSelectedAsset,
clearSelectedAssets,
getAssetById,
peekToggleVisibility,
peekToggleLock,
toggleSelectedAsset,
selectedAssets,
} = assetStore();
const {
groupHierarchy,
isGroup,
getGroupsContainingAsset,
getFlatGroupChildren,
setGroupExpanded,
addChildToGroup,
removeChildFromGroup,
getGroupsContainingGroup,
} = assetGroupStore();
const { projectId } = useParams(); const { projectId } = useParams();
const { push3D } = undoRedo3DStore(); const { push3D } = undoRedo3DStore();
const { builderSocket } = useSocketStore(); const { builderSocket } = useSocketStore();
@@ -355,7 +387,11 @@ export const Outline = () => {
}) })
.then((data) => { .then((data) => {
if (!data.message || !data.data) { if (!data.message || !data.data) {
echo.error(`Error ${asset.isVisible ? "locking" : "unlocking"} asset: ${asset.modelName}`); echo.error(
`Error ${asset.isVisible ? "locking" : "unlocking"} asset: ${
asset.modelName
}`
);
return; return;
} }
if (data.message === "Model updated successfully" && data.data) { if (data.message === "Model updated successfully" && data.data) {
@@ -374,14 +410,26 @@ export const Outline = () => {
}; };
updateAssetInScene(model, () => { updateAssetInScene(model, () => {
echo.info(`${asset.isVisible ? "Locked" : "Unlocked"} asset: ${model.modelName}`); echo.info(
`${asset.isVisible ? "Locked" : "Unlocked"} asset: ${
model.modelName
}`
);
}); });
} else { } else {
echo.error(`Error ${asset.isVisible ? "locking" : "unlocking"} asset: ${asset.modelName}`); echo.error(
`Error ${asset.isVisible ? "locking" : "unlocking"} asset: ${
asset.modelName
}`
);
} }
}) })
.catch(() => { .catch(() => {
echo.error(`Error ${asset.isVisible ? "locking" : "unlocking"} asset: ${asset.modelName}`); echo.error(
`Error ${asset.isVisible ? "locking" : "unlocking"} asset: ${
asset.modelName
}`
);
}); });
} else { } else {
const data = { const data = {
@@ -683,7 +731,14 @@ export const Outline = () => {
}); });
} }
}, },
[scene, isGroup, clearSelectedAssets, addSelectedAsset, getFlattenedHierarchy, toggleSelectedAsset] [
scene,
isGroup,
clearSelectedAssets,
addSelectedAsset,
getFlattenedHierarchy,
toggleSelectedAsset,
]
); );
const handleOptionClick = useCallback( const handleOptionClick = useCallback(
@@ -711,9 +766,17 @@ export const Outline = () => {
if (assetsToUpdate.length > 0) { if (assetsToUpdate.length > 0) {
if (assetsToUpdate.length === 1) { if (assetsToUpdate.length === 1) {
undoActions.push({ module: "builder", actionType: "Asset-Update", asset: assetsToUpdate[0] }); undoActions.push({
module: "builder",
actionType: "Asset-Update",
asset: assetsToUpdate[0],
});
} else { } else {
undoActions.push({ module: "builder", actionType: "Assets-Update", assets: assetsToUpdate }); undoActions.push({
module: "builder",
actionType: "Assets-Update",
assets: assetsToUpdate,
});
} }
push3D({ push3D({
@@ -745,9 +808,17 @@ export const Outline = () => {
if (assetsToUpdate.length > 0) { if (assetsToUpdate.length > 0) {
if (assetsToUpdate.length === 1) { if (assetsToUpdate.length === 1) {
undoActions.push({ module: "builder", actionType: "Asset-Update", asset: assetsToUpdate[0] }); undoActions.push({
module: "builder",
actionType: "Asset-Update",
asset: assetsToUpdate[0],
});
} else { } else {
undoActions.push({ module: "builder", actionType: "Assets-Update", assets: assetsToUpdate }); undoActions.push({
module: "builder",
actionType: "Assets-Update",
assets: assetsToUpdate,
});
} }
push3D({ push3D({
@@ -756,6 +827,11 @@ export const Outline = () => {
}); });
} }
} }
} else if (option === "focus") {
if (isGroup(item)) {
} else {
setContextAction("focusAsset");
}
} else if (option === "kebab") { } else if (option === "kebab") {
if (isGroup(item)) { if (isGroup(item)) {
} }

View File

@@ -147,7 +147,6 @@
gap: 6px; gap: 6px;
padding: 6px 12px; padding: 6px 12px;
border-radius: $border-radius-medium; border-radius: $border-radius-medium;
cursor: grab;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
background: transparent; background: transparent;
position: relative; position: relative;