import os index_path = r'z:\source\forgejo\spotnotes.app\static\assets\js\index.js' with open(index_path, 'r', encoding='utf-8') as f: content = f.read() # Add the filter input to the header header_replace = """

${window.SpotNotes.escapeHtml(currentName)}

${manageShareBtn} ${exportBtn}
${addNoteBtn} """ content = content.replace("""

${window.SpotNotes.escapeHtml(currentName)}

${manageShareBtn} ${exportBtn}
${addNoteBtn} """, header_replace) # Now, extract the rendering logic into a new function `window.SpotNotes.renderActiveNotesList` old_render_block = """ // Render Sidebar List sidebarBody.innerHTML = ''; if (notes.length === 0) { sidebarBody.innerHTML = '

No notes yet.

'; } notes.forEach(note => { const item = document.createElement('div'); item.className = 'sidebar-note-item'; let actionBtns = ''; if (window.SpotNotes.activePadCanWrite) { const escapedTitle = window.SpotNotes.escapeHtml(note.title).replace(/'/g, "\\\\'").replace(/"/g, '"'); const escapedContent = window.SpotNotes.escapeHtml(note.content).replace(/'/g, "\\\\'").replace(/"/g, '"').replace(/\\n/g, '\\\\n'); actionBtns = ` `; } else if (window.SpotNotes.activePadIsPublic) { actionBtns = ``; } const dateStr = new Date(note.created_at).toLocaleString(); item.innerHTML = `
${window.SpotNotes.escapeHtml(note.title)}
${window.SpotNotes.escapeHtml(note.content)}
${dateStr}
${note.lat.toFixed(5)}, ${note.lng.toFixed(5)}
Directions ${actionBtns}
`; item.addEventListener('click', () => { window.SpotNotes.stopTracking(); window.SpotNotes.map.setView([note.lat, note.lng], 16); }); sidebarBody.appendChild(item); }); window.SpotNotes.renderMapMarkers(); """ new_render_call = """ // Render Sidebar List window.SpotNotes.renderActiveNotesList(); """ content = content.replace(old_render_block, new_render_call) # Add event listener for the filter input inside loadNotesForPad filter_listener = """ const filterInput = document.getElementById('filter-active-notes'); if (filterInput) { filterInput.addEventListener('keyup', (e) => { window.SpotNotes.renderActiveNotesList(e.target.value); }); } """ content = content.replace(new_render_call, new_render_call + filter_listener) # Now append the function window.SpotNotes.renderActiveNotesList to the end of the file render_function = """ window.SpotNotes.renderActiveNotesList = function(filterText = '') { const sidebarBody = document.getElementById('sidebar-body'); if (!sidebarBody) return; sidebarBody.innerHTML = ''; const filterLower = filterText.toLowerCase(); const filteredNotes = window.SpotNotes.activeNotes.filter(note => { return note.title.toLowerCase().includes(filterLower) || note.content.toLowerCase().includes(filterLower); }); if (filteredNotes.length === 0) { sidebarBody.innerHTML = '

No notes match.

'; } filteredNotes.forEach(note => { const item = document.createElement('div'); item.className = 'sidebar-note-item'; let actionBtns = ''; if (window.SpotNotes.activePadCanWrite) { const escapedTitle = window.SpotNotes.escapeHtml(note.title).replace(/'/g, "\\\\'").replace(/"/g, '"'); const escapedContent = window.SpotNotes.escapeHtml(note.content).replace(/'/g, "\\\\'").replace(/"/g, '"').replace(/\\n/g, '\\\\n'); actionBtns = ` `; } else if (window.SpotNotes.activePadIsPublic) { actionBtns = ``; } const dateStr = new Date(note.created_at).toLocaleString(); item.innerHTML = `
${window.SpotNotes.escapeHtml(note.title)}
${window.SpotNotes.escapeHtml(note.content)}
${dateStr}
${note.lat.toFixed(5)}, ${note.lng.toFixed(5)}
Directions ${actionBtns}
`; item.addEventListener('click', () => { window.SpotNotes.stopTracking(); window.SpotNotes.map.setView([note.lat, note.lng], 16); }); sidebarBody.appendChild(item); }); // We do NOT call window.SpotNotes.renderMapMarkers() here, because we only want to filter the sidebar, not the map itself. // Wait, the task says: "filtering the existing activeNotes array before re-rendering the sidebar list". // It doesn't strictly say to filter the map markers, but maybe we should? // Usually a sidebar filter only filters the list if it says "Add a simple, fast text input filter floating above the note list in the sidebar... filtering the existing activeNotes array before re-rendering the sidebar list". // We will leave the map markers as they are to show all active notes. Or wait, if we only render the list, the map shows everything. Let's just leave the map markers as is (calling renderMapMarkers once on load). }; """ content += "\n" + render_function with open(index_path, 'w', encoding='utf-8') as f: f.write(content) print('Filtered active notes logic applied')