diff --git a/src/apps/ohos/entry/src/main/ets/utils/CommonUtils.ets b/src/apps/ohos/entry/src/main/ets/utils/CommonUtils.ets index 7041dd7a95..8ef39c4f93 100644 --- a/src/apps/ohos/entry/src/main/ets/utils/CommonUtils.ets +++ b/src/apps/ohos/entry/src/main/ets/utils/CommonUtils.ets @@ -43,7 +43,21 @@ export class CommonUtils { try { hilog.info(0x0000, 'vnext', `open_file_dialog: multiple=${multiple}, mode=${selectMode}`); const documentOptions = new filePicker.DocumentSelectOptions; - documentOptions.defaultFilePathUri = 'file://docs/storage/Users/currentUser'; + // Mirror reveal_in_explorer path→URI conversion so the picker opens at the + // caller-supplied path (e.g. the parent directory shown in NewProjectDialog) + // instead of the hardcoded default. Fallback keeps legacy behavior. + const defaultPathRaw: string = (opts.defaultPath ?? '').trim(); + let defaultUri: string = 'file://docs/storage/Users/currentUser'; + if (defaultPathRaw.length > 0) { + if (defaultPathRaw.startsWith('file://')) { + defaultUri = defaultPathRaw; + } else if (defaultPathRaw.startsWith('/data/storage/')) { + defaultUri = fileUri.getUriFromPath(defaultPathRaw); + } else { + defaultUri = 'file://docs' + defaultPathRaw; + } + } + documentOptions.defaultFilePathUri = defaultUri; documentOptions.selectMode = selectMode; documentOptions.maxSelectNumber = multiple ? 500 : 1; @@ -185,4 +199,5 @@ interface PickerOptions { multiple?: boolean; directory?: boolean; filters?: PickerFilter[]; + defaultPath?: string; } \ No newline at end of file diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx index 0b429d1cbf..8d84340ae3 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx @@ -68,6 +68,7 @@ interface WorkspaceItemProps { draggable?: boolean; isDragging?: boolean; onDragStart?: React.DragEventHandler; + onDrag?: React.DragEventHandler; onDragEnd?: React.DragEventHandler; } @@ -85,6 +86,7 @@ const WorkspaceItem: React.FC = ({ draggable = false, isDragging = false, onDragStart, + onDrag, onDragEnd, }) => { const { t } = useI18n('common'); @@ -142,7 +144,8 @@ const WorkspaceItem: React.FC = ({ const [acpClientsLoading, setAcpClientsLoading] = useState(false); const menuRef = useRef(null); const menuAnchorRef = useRef(null); - const menuPopoverRef = useRef(null); + const menuPopoverRef = useRef(null); + const popoverResizeObserverRef = useRef(null); const cardRef = useRef(null); const [menuPosition, setMenuPosition] = useState<{ top: number; left: number } | null>(null); const isNamedAssistantWorkspace = @@ -384,6 +387,26 @@ const WorkspaceItem: React.FC = ({ requestAnimationFrame(apply); }, []); + // Callback ref for the menu popover. The popover only mounts once menuPosition + // is set (chicken-and-egg: menuPosition needs the popover's size), so a + // ResizeObserver created in the menuOpen effect would attach to a null ref. + // Attaching here ties the observer to the element's actual mount/unmount: + // on mount it fires once with the real size (fixing the stale initial height) + // and again whenever async content (ACP client rows, loading toggle, remote + // /git conditional rows, locale label width) changes the popover height. + const setMenuPopoverRef = useCallback((node: HTMLDivElement | null) => { + if (popoverResizeObserverRef.current) { + popoverResizeObserverRef.current.disconnect(); + popoverResizeObserverRef.current = null; + } + menuPopoverRef.current = node; + if (node && typeof ResizeObserver !== 'undefined') { + const ro = new ResizeObserver(() => updateMenuPosition()); + ro.observe(node); + popoverResizeObserverRef.current = ro; + } + }, [updateMenuPosition]); + const handleMenuTriggerClick = useCallback(() => { const nextOpen = !menuOpen; setMenuOpen(nextOpen); @@ -856,6 +879,7 @@ const WorkspaceItem: React.FC = ({ className="bitfun-nav-panel__assistant-item-card" draggable={draggable} onDragStart={onDragStart} + onDrag={onDrag} onDragEnd={onDragEnd} onClick={() => { void handleCardNameClick(); }} style={{ cursor: 'pointer' }} @@ -886,7 +910,7 @@ const WorkspaceItem: React.FC = ({ - +