fix: split view — plus de panneaux vides, transfert auto de l'onglet
CI / lint (push) Failing after 9s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 14s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled
CI / lint (push) Failing after 9s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 14s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled
- _hasAnyTab(): empêche split si aucun onglet ouvert (tous les points d'entrée) - _copyActiveTabToNewPane(): copie l'onglet actif dans le nouveau panneau - Menu contextuel: l'onglet cliqué-droit est transféré dans le nouveau panneau - Raccourci clavier Ctrl+Alt+\: transfert l'onglet actif dans le nouveau panneau - Boutons split: vérifient _hasAnyTab() avant d'agir - Singleton ui.js: même comportement (split + transfert de l'onglet)
This commit is contained in:
+77
-10
@@ -69,11 +69,11 @@ function createPaneTabManager(paneId) {
|
|||||||
`;
|
`;
|
||||||
btns.querySelector('[data-action="split-right"]').addEventListener('click', (e) => {
|
btns.querySelector('[data-action="split-right"]').addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (window.PaneManager) window.PaneManager.splitRight();
|
if (window.PaneManager && window.PaneManager._hasAnyTab()) window.PaneManager.splitRight();
|
||||||
});
|
});
|
||||||
btns.querySelector('[data-action="split-down"]').addEventListener('click', (e) => {
|
btns.querySelector('[data-action="split-down"]').addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (window.PaneManager) window.PaneManager.splitDown();
|
if (window.PaneManager && window.PaneManager._hasAnyTab()) window.PaneManager.splitDown();
|
||||||
});
|
});
|
||||||
this._tabBar.appendChild(btns);
|
this._tabBar.appendChild(btns);
|
||||||
if (typeof safeCreateIcons === 'function') safeCreateIcons();
|
if (typeof safeCreateIcons === 'function') safeCreateIcons();
|
||||||
@@ -539,8 +539,23 @@ function createPaneTabManager(paneId) {
|
|||||||
menu.addEventListener('click', (e) => {
|
menu.addEventListener('click', (e) => {
|
||||||
const action = e.target.closest('.context-menu-item')?.dataset.action;
|
const action = e.target.closest('.context-menu-item')?.dataset.action;
|
||||||
if (action === 'moveTo') return; // handled by hover
|
if (action === 'moveTo') return; // handled by hover
|
||||||
if (action === 'splitRight') { if (pm) { pm.splitRight(); menu.remove(); return; } }
|
if (action === 'splitRight') {
|
||||||
else if (action === 'splitDown') { if (pm) { pm.splitDown(); menu.remove(); return; } }
|
if (pm && pm._hasAnyTab()) {
|
||||||
|
pm.splitRight();
|
||||||
|
// Transfer this specific tab to the new pane
|
||||||
|
const newPaneId = pm.panes.length - 1;
|
||||||
|
pm.transferTab(this.paneId, tabId, newPaneId);
|
||||||
|
menu.remove(); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action === 'splitDown') {
|
||||||
|
if (pm && pm._hasAnyTab()) {
|
||||||
|
pm.splitDown();
|
||||||
|
const newPaneId = pm.panes.length - 1;
|
||||||
|
pm.transferTab(this.paneId, tabId, newPaneId);
|
||||||
|
menu.remove(); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (action === 'closePane') { if (pm) { pm.closeActivePane(); menu.remove(); return; } }
|
else if (action === 'closePane') { if (pm) { pm.closeActivePane(); menu.remove(); return; } }
|
||||||
else if (action === 'close') this.close(tabId);
|
else if (action === 'close') this.close(tabId);
|
||||||
else if (action === 'closeOthers') this.closeOthers(tabId);
|
else if (action === 'closeOthers') this.closeOthers(tabId);
|
||||||
@@ -660,20 +675,60 @@ const PaneManager = {
|
|||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
splitRight() {
|
splitRight() {
|
||||||
if (this.panes.length >= PANE_MAX) return;
|
if (this.panes.length >= PANE_MAX) return;
|
||||||
|
// Don't split if no tab is open anywhere
|
||||||
|
if (!this._hasAnyTab()) return;
|
||||||
this.layout = 'horizontal';
|
this.layout = 'horizontal';
|
||||||
if (this.panes.length === 0) this._buildGrid(2);
|
if (this.panes.length === 0) {
|
||||||
else this._addPane();
|
this._buildGrid(2);
|
||||||
|
// Copy active tab to the new pane
|
||||||
|
this._copyActiveTabToNewPane();
|
||||||
|
} else {
|
||||||
|
this._addPane();
|
||||||
|
}
|
||||||
this._persist();
|
this._persist();
|
||||||
},
|
},
|
||||||
|
|
||||||
splitDown() {
|
splitDown() {
|
||||||
if (this.panes.length >= PANE_MAX) return;
|
if (this.panes.length >= PANE_MAX) return;
|
||||||
|
if (!this._hasAnyTab()) return;
|
||||||
this.layout = 'vertical';
|
this.layout = 'vertical';
|
||||||
if (this.panes.length === 0) this._buildGrid(2);
|
if (this.panes.length === 0) {
|
||||||
else this._addPane();
|
this._buildGrid(2);
|
||||||
|
this._copyActiveTabToNewPane();
|
||||||
|
} else {
|
||||||
|
this._addPane();
|
||||||
|
}
|
||||||
this._persist();
|
this._persist();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** Check if any pane has at least one tab */
|
||||||
|
_hasAnyTab() {
|
||||||
|
if (!this.isSplit()) {
|
||||||
|
// Check singleton in single-pane mode
|
||||||
|
if (window._singletonTabManager && window._singletonTabManager._tabs.length > 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const tm of Object.values(this.tabManagers)) {
|
||||||
|
if (tm._tabs && tm._tabs.length > 0) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Copy the active tab to the newly created last pane */
|
||||||
|
_copyActiveTabToNewPane() {
|
||||||
|
const newPaneId = this.panes.length - 1;
|
||||||
|
const srcTm = this.tabManagers[this.activePaneId];
|
||||||
|
const dstTm = this.tabManagers[newPaneId];
|
||||||
|
if (!srcTm || !dstTm || !srcTm._activeTabId) return;
|
||||||
|
const cache = srcTm._tabCache[srcTm._activeTabId];
|
||||||
|
if (cache) {
|
||||||
|
setTimeout(() => {
|
||||||
|
dstTm.open(cache.vault, cache.path);
|
||||||
|
}, 150);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Close pane
|
// Close pane
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
@@ -1268,11 +1323,23 @@ if (typeof window !== 'undefined') {
|
|||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.ctrlKey && e.altKey && !e.shiftKey && e.key === '\\') {
|
if (e.ctrlKey && e.altKey && !e.shiftKey && e.key === '\\') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
PaneManager.splitRight();
|
if (PaneManager._hasAnyTab()) {
|
||||||
|
PaneManager.splitRight();
|
||||||
|
// Transfer active tab to new pane
|
||||||
|
const tm = PaneManager.getActiveTabManager();
|
||||||
|
if (tm && tm._activeTabId) {
|
||||||
|
setTimeout(() => {
|
||||||
|
const newPaneId = PaneManager.panes.length - 1;
|
||||||
|
PaneManager.transferTab(PaneManager.activePaneId === newPaneId ? 0 : PaneManager.activePaneId, tm._activeTabId, newPaneId);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (e.ctrlKey && e.altKey && e.shiftKey && e.key === '\\') {
|
if (e.ctrlKey && e.altKey && e.shiftKey && e.key === '\\') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
PaneManager.splitDown();
|
if (PaneManager._hasAnyTab()) {
|
||||||
|
PaneManager.splitDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Close active pane
|
// Close active pane
|
||||||
if (e.ctrlKey && e.altKey && !e.shiftKey && (e.key === 'w' || e.key === 'W') && PaneManager.isSplit()) {
|
if (e.ctrlKey && e.altKey && !e.shiftKey && (e.key === 'w' || e.key === 'W') && PaneManager.isSplit()) {
|
||||||
|
|||||||
+16
-2
@@ -2351,8 +2351,22 @@ export const TabManager = {
|
|||||||
|
|
||||||
menu.addEventListener("click", (e) => {
|
menu.addEventListener("click", (e) => {
|
||||||
const action = e.target.closest(".context-menu-item")?.dataset.action;
|
const action = e.target.closest(".context-menu-item")?.dataset.action;
|
||||||
if (action === "splitRight") { if (window.PaneManager) { window.PaneManager.splitRight(); menu.remove(); return; } }
|
if (action === "splitRight") {
|
||||||
else if (action === "splitDown") { if (window.PaneManager) { window.PaneManager.splitDown(); menu.remove(); return; } }
|
if (window.PaneManager && window.PaneManager._hasAnyTab && window.PaneManager._hasAnyTab()) {
|
||||||
|
window.PaneManager.splitRight();
|
||||||
|
const newPaneId = window.PaneManager.panes.length - 1;
|
||||||
|
window.PaneManager.transferTab(0, tabId, newPaneId);
|
||||||
|
menu.remove(); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action === "splitDown") {
|
||||||
|
if (window.PaneManager && window.PaneManager._hasAnyTab && window.PaneManager._hasAnyTab()) {
|
||||||
|
window.PaneManager.splitDown();
|
||||||
|
const newPaneId = window.PaneManager.panes.length - 1;
|
||||||
|
window.PaneManager.transferTab(0, tabId, newPaneId);
|
||||||
|
menu.remove(); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (action === "closePane") { if (window.PaneManager) { window.PaneManager.closeActivePane(); menu.remove(); return; } }
|
else if (action === "closePane") { if (window.PaneManager) { window.PaneManager.closeActivePane(); menu.remove(); return; } }
|
||||||
else if (action === "close") this.close(tabId);
|
else if (action === "close") this.close(tabId);
|
||||||
else if (action === "closeOthers") this.closeOthers(tabId);
|
else if (action === "closeOthers") this.closeOthers(tabId);
|
||||||
|
|||||||
Reference in New Issue
Block a user