diff --git a/app/templates/library.html b/app/templates/library.html index c629e4b..b31f19e 100644 --- a/app/templates/library.html +++ b/app/templates/library.html @@ -220,7 +220,7 @@
Last edited
Last visited
-
+
@@ -313,12 +313,13 @@ function libraryPage() { peekFavorited: false, peekMoreOpen: false, - // ── Computed flat list (NOT a getter — Alpine 3.14.9 bug) ── + // ── Computed flat list ── flatItems: [], - tableHtml: '', - _buildTableHtml() { + _renderTable() { var self = this; + var body = document.getElementById('lib-table-body'); + if (!body) return; var html = ''; for (var i = 0; i < this.flatItems.length; i++) { var item = this.flatItems[i]; @@ -346,7 +347,7 @@ function libraryPage() { html += '' + (item.icon || '\ud83d\udcc4') + ''; // Title or rename input if (isRenaming) { - html += ''; + html += ''; } else { html += '' + self._escHtml(item.title) + ''; } @@ -365,7 +366,7 @@ function libraryPage() { html += '
' + self.formatTime(item.visited_at) + '
'; html += ''; } - this.tableHtml = html; + body.innerHTML = html; }, _escHtml(s) { var d=document.createElement('div'); d.textContent = s||''; return d.innerHTML; }, @@ -384,7 +385,7 @@ function libraryPage() { this.flatItems.splice(0, this.flatItems.length, ...result); this.selectedCount = Object.keys(this.selected).length; this.allSelected = this.flatItems.length > 0 && this.selectedCount === this.flatItems.length; - this._buildTableHtml(); + this._renderTable(); }, // ── Global dispatch (bypasses Alpine x-for reactivity issues) ── @@ -405,7 +406,10 @@ function libraryPage() { }, commitRenameById(id) { var item = this._findItem(id); - if (!item) { this.renamingId = null; this._buildTableHtml(); return; } + if (!item) { this.renamingId = null; this._renderTable(); return; } + // Read value from the input + var inp = document.getElementById('rename-inp-' + id); + if (inp) this.renameValue = inp.value; this.commitRename(item); }, openItemById(id) { @@ -524,7 +528,7 @@ function libraryPage() { console.log('[Library] loaded ' + this.items.length + ' items'); this._markTree(this.items, 0); this._recomputeFlatItems(); - this._buildTableHtml(); + this._renderTable(); console.log('[Library] flatItems after recompute: ' + this.flatItems.length); // Force Alpine to re-render (known issue with x-for in 3.14.9) var self = this; @@ -568,7 +572,7 @@ function libraryPage() { delete this.expanded[item.id]; this.expanded = Object.assign({}, this.expanded); this._recomputeFlatItems(); - this._buildTableHtml(); + this._renderTable(); return; } // Expand — load children if not loaded yet @@ -586,7 +590,7 @@ function libraryPage() { } } this._recomputeFlatItems(); - this._buildTableHtml(); + this._renderTable(); }, _markChildren(nodes, depth) { @@ -608,7 +612,7 @@ function libraryPage() { } this.selected = Object.assign({}, this.selected); this._recomputeFlatItems(); - this._buildTableHtml(); + this._renderTable(); }, toggleSelectAll() { @@ -622,14 +626,14 @@ function libraryPage() { this.selected = s; } this._recomputeFlatItems(); - this._buildTableHtml(); + this._renderTable(); }, clearSelection() { this.selected = {}; this.moreOpen = false; this._recomputeFlatItems(); - this._buildTableHtml(); + this._renderTable(); }, // ── Multi-select actions ── @@ -678,22 +682,18 @@ function libraryPage() { startRename(item) { this.renamingId = item.id; this.renameValue = item.title; - this._buildTableHtml(); - var self = this; - this.$nextTick(function() { - var inp = document.querySelector('.row-title input, [onkeydown*=\"commitRenameById\"]'); - // Try to find the rename input that was just created - var inputs = document.querySelectorAll('#lib-table-body input'); - for (var i = 0; i < inputs.length; i++) { - if (inputs[i].value === item.title) { inputs[i].focus(); inputs[i].select(); break; } - } - }); + this._renderTable(); + // Focus the rename input + setTimeout(function() { + var inp = document.getElementById('rename-inp-' + item.id); + if (inp) { inp.focus(); inp.select(); } + }, 50); }, async commitRename(item) { var newName = (this.renameValue || '').trim(); this.renamingId = null; - if (!newName || newName === item.title) { this._buildTableHtml(); return; } + if (!newName || newName === item.title) { this._renderTable(); return; } try { var r = await fetch('/api/pages/' + item.id + '/rename', { method:'PUT', headers:{'Content-Type':'application/json'}, @@ -703,7 +703,7 @@ function libraryPage() { item.title = newName; } } catch(e) {} - this._buildTableHtml(); + this._renderTable(); }, // ── Add new ── @@ -834,44 +834,5 @@ function libraryPage() { } }; } -// SortableJS — drag-and-drop reorder in library table -document.addEventListener('alpine:init', function() { - var initSortable = function() { - var body = document.getElementById('lib-table-body'); - if (!body || typeof Sortable === 'undefined') return; - // Clean up any existing instance - if (body._sortable) body._sortable.destroy(); - body._sortable = new Sortable(body, { - handle: '.drag-handle', - animation: 150, - ghostClass: 'sortable-ghost', - onEnd: async function(evt) { - var itemEl = evt.item; - var itemId = itemEl.getAttribute('data-lib-id'); - var prevEl = evt.item.previousElementSibling; - var nextEl = evt.item.nextElementSibling; - var prevId = prevEl ? prevEl.getAttribute('data-lib-id') : null; - var nextId = nextEl ? nextEl.getAttribute('data-lib-id') : null; - if (!itemId) return; - try { - await fetch('/api/pages/' + itemId + '/move', { - method: 'PUT', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({before_id: nextId || null, after_id: prevId || null}) - }); - } catch(e) {} - } - }); - }; - // Watch for table body updates with MutationObserver - var target = document.getElementById('lib-table'); - if (target) { - var observer = new MutationObserver(function() { - setTimeout(initSortable, 200); - }); - observer.observe(target, {childList: true, subtree: true}); - } - initSortable(); -}); {% endblock %}