- clic sur le titre: la page d'accueil s'ouvre dans un onglet Accueil (icone Maison) epingle en tete de barre, reactivable d'un clic (onglet propre au panneau actif en split)
- page de navigation: menus contextuels des repertoires et des fichiers identiques a ceux de la sidebar, clic sur la racine d'un vault qui ouvre la vue, icone dossier a la couleur de l'arbre de navigation
- BUG-101: bloc « Keyboard shortcuts for tabs » duplique dans ui.js (un seul Ctrl+W fermait deux onglets)
- BUG-102: le menu contextuel se refermait 10 ms apres son ouverture (scroll de reflow des icones lucide)
Une session d'edition inline (Editer/Forge) qui possede la zone de contenu etait detruite par deux chemins qui vident cette zone : activation d'onglet (TabManager.activate, PaneTabManager.activate) -> detachInlineEditor() avant le placeholder ; evenement SSE index_updated -> reloadExternalWrite() recharge le tampon de l'editeur au lieu de re-rendre la vue lecture. Nouveau helper queryEditor() ; closeEditor() remet le conteneur dans la modale avant de restaurer en-tete/pied/marque. docs/CONTRIBUTING.md documente scripts/install-hooks.sh.
- la copie de l onglet actif etait dedupe (fichier deja ouvert dans le pane source) et le transfert clavier (200ms) vidait le pane source -> auto-collapse -> grid disparu
- comportement coherent avec le menu contextuel : pane vide, l utilisateur y glisse ses fichiers
- search.js : le dropdown d autocomplete ne se rouvre plus 500ms apres un hide (la recherche le rouvrait et bloquait les clics toolbar - test Forge)
- ui.js + pane-manager.js : le split via menu contextuel ne transfert plus l onglet en synchrone (vidait le pane source -> auto-collapse -> grid disparu)
- split-view.spec.js : navigation clavier attend la copie asynchrone (setTimeout 150ms qui reactivait pane 0)
- split-view.spec.js : drag depuis l arbre via dragTo (drag natif HTML5)
Three fixes for drag-and-drop in split view (#75):
1. Tree drag-to-split: edge zone detection now runs BEFORE the tree/tab
dispatch, so dragging a sidebar file to the right/bottom edge of a
single pane correctly creates a split and opens the file in the new
pane (was: tree check returned early before edge zone logic).
2. Cross-pane transfer consistency: transferTab() now tracks pane count
before the transfer — if closePane() fires inside transferTabTo()
(source pane becomes empty), the DOM is rebuilt and the original
targetTm reference is stale. After close, re-lookup the tab manager
that actually holds the transferred tab before _renderTabs()+activate.
3. dragdrop.js flicker: onDragLeave() now checks relatedTarget instead
of unconditionally clearing highlights on every child boundary.
- _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)
Refonte complète du layout grid:
- _computePanePositions: positions explicites (row/col/span) selon n et layout
- _createPaneAt: grid-row/grid-column explicites sur chaque .pane-container
- _addAllResizeHandles: handles placés aux bonnes positions grid
- _rebuildResizeHandles: nettoie et recrée les handles après add/remove
- closePane: repositionne les panneaux restants + rebuild handles
- 3 panneaux horizontal: 2 en haut, 1 pleine largeur en bas
- 3 panneaux vertical: 1 pleine hauteur à gauche, 2 à droite
- 4 panneaux: grille 2×2
Fix aussi: _addPane avec positions explicites + rebuild handles
Problème: le lazy rendering masquait le contenu du panneau non-sélectionné
→ split view devenait inutile (un seul panneau visible à la fois)
→ Solution: supprimé display:none dans setActivePane, tous les panneaux visibles
Test mis à jour: test_panes_remain_visible_when_inactive
C1b: Sous-menu « Déplacer vers... » (flyout hover) — liste les autres panneaux
D2: Drag depuis l'arborescence vers panneau — format 'tree:{vault,path}'
E3: Rendu paresseux — display:none sur contenu des panneaux inactifs
E4: Verrouillage éditeur — même fichier déjà ouvert → focus le panneau existant
G3: Bouton reset (🔄 Réinitialiser les panneaux) dans la palette
ROADMAP: section 75 marquée ✅ Complété (reste I2/I3 tests)
Ajouts:
- C3: Boutons Split ⊞→ ⊞↓ dans la barre d'onglets (visibles au survol)
- C2: Ctrl+Alt+←/→/↑/↓ navigation entre panneaux
- C2: Ctrl+Shift+Alt+W fermer tous les autres panneaux
- H1: 5 commandes palette (Split R/D, Close Pane, Focus Next/Prev)
- ROADMAP.md: section 75 mise à jour avec statut 80% complété
CSS: .tab-split-buttons, .tab-split-btn avec opacity hover
_buildGrid: quand on passe de single-pane à multi-pane, migre les onglets
du TabManager singleton vers le PaneTabManager du pane 0.
Sans ça, transferTab() ne trouvait pas l'onglet (il était resté dans le singleton).
_collapseToSingle: migration inverse (PaneTabManager → singleton)
quand on ferme le dernier split.
- dragstart: setData 'text/plain' (universel, pas de custom MIME)
- drop container + tab: getData('text/plain')
- console.log dans le drop handler pour diagnostic
- Suppression application/obsigate-tab (non fiable cross-browser)
Bug 1 — bookmarks/récents sans tab:
dashboard.js:135: openFile() → TabManager.openPreview()
_createCard() est partagé par DashboardRecentWidget ET DashboardBookmarkWidget
Bug 2 — drag-to-split bloqué en single-pane:
La condition 'if (dragData.paneId === paneId) return' empêchait le split
car en single-pane, le drag part du pane 0 et drop sur le pane 0.
→ Supprimé. Edge detection vérifiée avant, cross-pane vérifié après.
Même pane + pas edge → laissé au tab handler (reorder).
Cause: _setupPaneDropZone était uniquement appelé sur .pane-container (créé par split).
En mode single-pane, le DOM est .content-wrapper > .tab-bar + .content-area sans wrapper.
→ Ajout de _setupPaneDropZone sur .content-wrapper dans PaneManager.init()
→ CSS: position:relative sur .content-wrapper pour les indicateurs absolute
Changements:
- pane-manager.js: init() ajoute drop zone sur .content-wrapper (single-pane)
- style.css: position:relative sur .content-wrapper
- dragstart: effectAllowed='move' + double setData (obsigate-tab + text/plain)
- dragenter/dragover: acceptent TOUS les drags (plus de filtre types.includes cassant)
- drop: fallback text/plain si application/obsigate-tab indisponible
- console.debug au lieu de silent catch pour diagnostiquer les erreurs restantes
1. types.includes → Array.from(types).includes (DOMStringList n'a pas .includes)
2. dragleave: compteur _dragCounter empêche clear sur child enter/leave
3. drag-to-split: zone recalculée dans drop handler (plus de closure corrompue)
4. drop: stopPropagation + skip same-paneId dans container handler
5. dragenter: appel preventDefault pour accepter le drop dès l'entrée
- _setupPaneDropZone: dragover/drop sur .pane-container (fonctionne même si tab bar vide)
- Drag-to-split: déposer un onglet dans les 25% droit → split right, 25% bas → split down
- Indicateurs visuels: zone bleue semi-transparente au drop, tab-bar dashed outline
- stopPropagation dans le drop handler des tabs pour éviter double-fire
- CSS: .pane-drop-zone-indicator, .tab-bar.drop-target, position:relative sur pane-container
- ui.js: window.TabManager et window._singletonTabManager exposés dans init()
- pane-manager.js: référence corrigée vers window.TabManager (n'était pas en scope)
- PaneTabManager.close/transferTabTo: ferme automatiquement le panneau quand vide (sauf dernier)
- Déployé sur 192.168.30.101:2020, 307 tests verts
- PaneTabManager factory: chaque panneau a sa propre instance avec ses propres onglets
- Drag & drop d'onglets entre panneaux (application/obsigate-tab dataTransfer)
- Split copie l'onglet actif dans le nouveau panneau
- TabManager singleton: délégation automatique vers le panneau actif en mode split
- Persistance complète par panneau (tabs, activeTab, previewTab)
- viewer.js: getContentArea() priorise window._activePaneContentArea
- 307 tests verts, déployé sur 192.168.30.101:2020
#74 — Support PDF complet:
- backend/pdf_reader.py — pymupdf/pypdf text extraction
- .pdf added to SUPPORTED_EXTENSIONS in indexer.py
- PDF-aware file view API endpoint (metadata, text preview)
- Streaming endpoint /api/file/{vault}/pdf/stream
- Frontend PDF viewer with iframe, toolbar, download
- CSS for PDF viewer container
#75 — Split View (PaneManager):
- New module frontend/js/pane-manager.js — ES module
- 1-4 pane CSS grid with resize handles
- Split right/down via keyboard (Ctrl+Alt+\) or PaneManager API
- Persistence in localStorage (obsigate-panes)
- Collapse to single pane, per-pane active state
285 tests passent