Stage 312: PR #1790 — fix: keep workspace open from preview breadcrumb by @Michaelyklam
This commit is contained in:
commit
b62f9dbbf8
5 changed files with 67 additions and 6 deletions
BIN
docs/pr-media/1785/workspace-preview-breadcrumb-before.png
Normal file
BIN
docs/pr-media/1785/workspace-preview-breadcrumb-before.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
BIN
docs/pr-media/1785/workspace-root-breadcrumb-fixed.png
Normal file
BIN
docs/pr-media/1785/workspace-root-breadcrumb-fixed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
|
|
@ -820,10 +820,11 @@ $('importFileInput').onchange=async(e)=>{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// btnRefreshFiles is now panel-icon-btn in header (see HTML)
|
// btnRefreshFiles is now panel-icon-btn in header (see HTML)
|
||||||
function clearPreview(){
|
function clearPreview(opts={}){
|
||||||
|
const keepPanelOpen=!!(opts&&opts.keepPanelOpen);
|
||||||
// Restore directory breadcrumb after closing file preview
|
// Restore directory breadcrumb after closing file preview
|
||||||
if(typeof renderBreadcrumb==='function') renderBreadcrumb();
|
if(typeof renderBreadcrumb==='function') renderBreadcrumb();
|
||||||
const closePanelAfter=_workspacePanelMode==='preview';
|
const closePanelAfter=_workspacePanelMode==='preview'&&!keepPanelOpen;
|
||||||
const pa=$('previewArea');if(pa)pa.classList.remove('visible');
|
const pa=$('previewArea');if(pa)pa.classList.remove('visible');
|
||||||
const pi=$('previewImg');if(pi){pi.onerror=null;pi.src='';}
|
const pi=$('previewImg');if(pi){pi.onerror=null;pi.src='';}
|
||||||
const pdf=$('previewPdfFrame');if(pdf)pdf.src='';
|
const pdf=$('previewPdfFrame');if(pdf)pdf.src='';
|
||||||
|
|
@ -834,6 +835,7 @@ function clearPreview(){
|
||||||
const ft=$('fileTree');if(ft)ft.style.display='';
|
const ft=$('fileTree');if(ft)ft.style.display='';
|
||||||
_previewCurrentPath='';_previewCurrentMode='';_previewDirty=false;
|
_previewCurrentPath='';_previewCurrentMode='';_previewDirty=false;
|
||||||
if(closePanelAfter)closeWorkspacePanel();
|
if(closePanelAfter)closeWorkspacePanel();
|
||||||
|
else if(keepPanelOpen&&_workspacePanelMode==='preview')openWorkspacePanel('browse');
|
||||||
else syncWorkspacePanelUI();
|
else syncWorkspacePanelUI();
|
||||||
}
|
}
|
||||||
$('btnClearPreview').onclick=handleWorkspaceClose;
|
$('btnClearPreview').onclick=handleWorkspaceClose;
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,9 @@ async function loadDir(path){
|
||||||
}
|
}
|
||||||
if(typeof clearPreview==='function'){
|
if(typeof clearPreview==='function'){
|
||||||
if(typeof _previewDirty!=='undefined'&&_previewDirty){
|
if(typeof _previewDirty!=='undefined'&&_previewDirty){
|
||||||
showConfirmDialog({title:t('unsaved_confirm'),message:'',confirmLabel:'Discard',danger:true,focusCancel:true}).then(ok=>{if(ok)clearPreview();});
|
showConfirmDialog({title:t('unsaved_confirm'),message:'',confirmLabel:'Discard',danger:true,focusCancel:true}).then(ok=>{if(ok)clearPreview({keepPanelOpen:true});});
|
||||||
}else{
|
}else{
|
||||||
clearPreview();
|
clearPreview({keepPanelOpen:true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fetch git info for workspace root (non-blocking)
|
// Fetch git info for workspace root (non-blocking)
|
||||||
|
|
@ -337,7 +337,7 @@ function renderFileBreadcrumb(filePath) {
|
||||||
const root = document.createElement('span');
|
const root = document.createElement('span');
|
||||||
root.className = 'breadcrumb-seg breadcrumb-link';
|
root.className = 'breadcrumb-seg breadcrumb-link';
|
||||||
root.textContent = '~';
|
root.textContent = '~';
|
||||||
root.onclick = () => { clearPreview(); loadDir('.'); };
|
root.onclick = () => { loadDir('.'); };
|
||||||
bar.appendChild(root);
|
bar.appendChild(root);
|
||||||
|
|
||||||
const parts = filePath.split('/');
|
const parts = filePath.split('/');
|
||||||
|
|
@ -354,7 +354,7 @@ function renderFileBreadcrumb(filePath) {
|
||||||
if (i < parts.length - 1) {
|
if (i < parts.length - 1) {
|
||||||
seg.className = 'breadcrumb-seg breadcrumb-link';
|
seg.className = 'breadcrumb-seg breadcrumb-link';
|
||||||
const target = accumulated;
|
const target = accumulated;
|
||||||
seg.onclick = () => { clearPreview(); loadDir(target); };
|
seg.onclick = () => { loadDir(target); };
|
||||||
} else {
|
} else {
|
||||||
seg.className = 'breadcrumb-seg breadcrumb-current';
|
seg.className = 'breadcrumb-seg breadcrumb-current';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
tests/test_issue1785_workspace_preview_breadcrumb.py
Normal file
59
tests/test_issue1785_workspace_preview_breadcrumb.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
BOOT_JS = Path("static/boot.js").read_text(encoding="utf-8")
|
||||||
|
WORKSPACE_JS = Path("static/workspace.js").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def _function_block(src: str, name: str) -> str:
|
||||||
|
marker = f"function {name}("
|
||||||
|
start = src.find(marker)
|
||||||
|
assert start != -1, f"{name}() not found"
|
||||||
|
params_end = src.find("){", start)
|
||||||
|
assert params_end != -1, f"{name}() body not found"
|
||||||
|
brace = params_end + 1
|
||||||
|
depth = 0
|
||||||
|
for idx in range(brace, len(src)):
|
||||||
|
ch = src[idx]
|
||||||
|
if ch == "{":
|
||||||
|
depth += 1
|
||||||
|
elif ch == "}":
|
||||||
|
depth -= 1
|
||||||
|
if depth == 0:
|
||||||
|
return src[start : idx + 1]
|
||||||
|
raise AssertionError(f"{name}() body did not close")
|
||||||
|
|
||||||
|
|
||||||
|
def test_clear_preview_can_keep_preview_only_panel_open_for_directory_navigation():
|
||||||
|
"""#1785: leaving preview via a directory breadcrumb should switch to browse mode, not close."""
|
||||||
|
block = _function_block(BOOT_JS, "clearPreview")
|
||||||
|
assert "keepPanelOpen" in block, (
|
||||||
|
"clearPreview() needs an explicit keep-open option so breadcrumb/directory "
|
||||||
|
"navigation can leave preview-only mode without closing the workspace panel."
|
||||||
|
)
|
||||||
|
assert "_workspacePanelMode==='preview'&&!keepPanelOpen" in block.replace(" ", ""), (
|
||||||
|
"Preview-only close behavior should remain for the X button, but must be gated "
|
||||||
|
"off when directory navigation requests keepPanelOpen."
|
||||||
|
)
|
||||||
|
assert "openWorkspacePanel('browse')" in block or '_setWorkspacePanelMode("browse")' in block, (
|
||||||
|
"When keepPanelOpen is requested from preview-only mode, clearPreview() should "
|
||||||
|
"transition the workspace panel to browse mode so the root listing remains visible."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_dir_keeps_workspace_panel_open_when_clearing_preview():
|
||||||
|
"""#1785: loadDir('.') from the ~ breadcrumb should reveal the listing, not collapse the panel."""
|
||||||
|
block = _function_block(WORKSPACE_JS, "loadDir")
|
||||||
|
assert "clearPreview({keepPanelOpen:true})" in block.replace(" ", ""), (
|
||||||
|
"Directory navigation clears previews as part of showing the file tree; that clear "
|
||||||
|
"must keep the workspace panel open for breadcrumb navigation from preview mode."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_file_preview_breadcrumb_uses_directory_navigation_for_root():
|
||||||
|
block = _function_block(WORKSPACE_JS, "renderFileBreadcrumb")
|
||||||
|
assert "loadDir('.')" in block, "The preview root breadcrumb should navigate to the workspace root."
|
||||||
|
assert "clearPreview(); loadDir('.')" not in block, (
|
||||||
|
"The preview root breadcrumb should not do a close-style preview clear before "
|
||||||
|
"directory navigation; loadDir() owns the keep-open preview clear."
|
||||||
|
)
|
||||||
Loading…
Reference in a new issue