feat: enhance LoraModal with notes hint and cleanup functionality on close

This commit is contained in:
Will Miao
2025-06-21 20:02:19 +08:00
parent fa0902dc74
commit ba2e42b06e
3 changed files with 36 additions and 36 deletions

View File

@@ -107,25 +107,13 @@
opacity: 0.5; opacity: 0.5;
} }
.save-btn { .notes-hint {
padding: 4px 8px; font-size: 0.8em;
background: var(--lora-accent); color: var(--text-color);
border: none; opacity: 0.7;
border-radius: var(--border-radius-xs); margin-left: 5px;
color: white; cursor: help;
cursor: pointer; position: relative; /* Add positioning context */
transition: opacity 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
.save-btn:hover {
opacity: 0.9;
}
.save-btn i {
font-size: 0.9em;
} }
@media (max-width: 640px) { @media (max-width: 640px) {

View File

@@ -116,12 +116,9 @@ export function showLoraModal(lora) {
</div> </div>
${renderTriggerWords(escapedWords, lora.file_path)} ${renderTriggerWords(escapedWords, lora.file_path)}
<div class="info-item notes"> <div class="info-item notes">
<label>Additional Notes</label> <label>Additional Notes <i class="fas fa-info-circle notes-hint" title="Press Enter to save, Shift+Enter for new line"></i></label>
<div class="editable-field"> <div class="editable-field">
<div class="notes-content" contenteditable="true" spellcheck="false">${lora.notes || 'Add your notes here...'}</div> <div class="notes-content" contenteditable="true" spellcheck="false">${lora.notes || 'Add your notes here...'}</div>
<button class="save-btn" data-action="save-notes">
<i class="fas fa-save"></i>
</button>
</div> </div>
</div> </div>
<div class="info-item full-width"> <div class="info-item full-width">
@@ -171,7 +168,14 @@ export function showLoraModal(lora) {
</div> </div>
`; `;
modalManager.showModal('loraModal', content); modalManager.showModal('loraModal', content, null, function() {
// Clean up all handlers when modal closes
const modalElement = document.getElementById('loraModal');
if (modalElement && modalElement._clickHandler) {
modalElement.removeEventListener('click', modalElement._clickHandler);
delete modalElement._clickHandler;
}
});
setupEditableFields(lora.file_path); setupEditableFields(lora.file_path);
setupShowcaseScroll('loraModal'); setupShowcaseScroll('loraModal');
setupTabSwitching(); setupTabSwitching();
@@ -206,8 +210,11 @@ export function showLoraModal(lora) {
function setupEventHandlers(filePath) { function setupEventHandlers(filePath) {
const modalElement = document.getElementById('loraModal'); const modalElement = document.getElementById('loraModal');
// Use event delegation to handle clicks // Remove existing event listeners first
modalElement.addEventListener('click', async (event) => { modalElement.removeEventListener('click', handleModalClick);
// Create and store the handler function
function handleModalClick(event) {
const target = event.target.closest('[data-action]'); const target = event.target.closest('[data-action]');
if (!target) return; if (!target) return;
@@ -217,16 +224,17 @@ function setupEventHandlers(filePath) {
case 'close-modal': case 'close-modal':
modalManager.closeModal('loraModal'); modalManager.closeModal('loraModal');
break; break;
case 'save-notes':
await saveNotes(filePath);
break;
case 'scroll-to-top': case 'scroll-to-top':
scrollToTop(target); scrollToTop(target);
break; break;
} }
}); }
// Add the event listener with the named function
modalElement.addEventListener('click', handleModalClick);
// Store reference to the handler on the element for potential cleanup
modalElement._clickHandler = handleModalClick;
} }
async function saveNotes(filePath) { async function saveNotes(filePath) {

View File

@@ -299,7 +299,7 @@ export class ModalManager {
return null; return null;
} }
showModal(id, content = null, onCloseCallback = null) { showModal(id, content = null, onCloseCallback = null, cleanupCallback = null) {
const modal = this.getModal(id); const modal = this.getModal(id);
if (!modal) return; if (!modal) return;
@@ -314,9 +314,8 @@ export class ModalManager {
} }
// Store callback // Store callback
if (onCloseCallback) { modal.onCloseCallback = onCloseCallback;
modal.onCloseCallback = onCloseCallback; modal.cleanupCallback = cleanupCallback;
}
// Store current scroll position before showing modal // Store current scroll position before showing modal
this.scrollPosition = window.scrollY; this.scrollPosition = window.scrollY;
@@ -362,6 +361,11 @@ export class ModalManager {
modal.onCloseCallback(); modal.onCloseCallback();
modal.onCloseCallback = null; modal.onCloseCallback = null;
} }
if (modal.cleanupCallback) {
modal.cleanupCallback();
modal.cleanupCallback = null;
}
} }
handleEscape(e) { handleEscape(e) {