diff --git a/src/main.js b/src/main.js
index df17aa5..2176932 100644
--- a/src/main.js
+++ b/src/main.js
@@ -2098,63 +2098,158 @@ function renderWorldInfoList(entries) {
// Add new World Info entry
async function handleAddWorldInfoEntry() {
- const keys = prompt('Enter keywords (comma-separated):\nExample: John, John Smith');
- if (!keys) return;
+ const listContainer = document.getElementById('worldinfo-list');
- const content = prompt('Enter the content to inject when keywords are found:');
- if (!content) return;
+ // Check if form already exists
+ if (document.getElementById('worldinfo-add-form')) return;
- const priorityStr = prompt('Enter priority (higher = injected first, default 0):', '0');
- const priority = parseInt(priorityStr) || 0;
+ // Create inline form
+ const formDiv = document.createElement('div');
+ formDiv.id = 'worldinfo-add-form';
+ formDiv.className = 'worldinfo-entry worldinfo-edit-form';
- try {
- const keysArray = keys.split(',').map(k => k.trim()).filter(k => k);
- await invoke('add_world_info_entry', {
- characterId: currentCharacter.id,
- keys: keysArray,
- content: content.trim(),
- priority,
- caseSensitive: false
- });
+ formDiv.innerHTML = `
+
+
Add World Info Entry
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
- // Reload settings
- await loadRoleplaySettings();
- } catch (error) {
- console.error('Failed to add World Info entry:', error);
- alert(`Failed to add entry: ${error}`);
- }
+ listContainer.prepend(formDiv);
+
+ // Focus first input
+ document.getElementById('wi-add-keys').focus();
+
+ // Handle cancel
+ document.getElementById('wi-add-cancel').addEventListener('click', () => {
+ formDiv.remove();
+ });
+
+ // Handle save
+ document.getElementById('wi-add-save').addEventListener('click', async () => {
+ const keys = document.getElementById('wi-add-keys').value.trim();
+ const content = document.getElementById('wi-add-content').value.trim();
+ const priority = parseInt(document.getElementById('wi-add-priority').value) || 0;
+
+ if (!keys || !content) {
+ alert('Keywords and content are required');
+ return;
+ }
+
+ try {
+ const keysArray = keys.split(',').map(k => k.trim()).filter(k => k);
+ await invoke('add_world_info_entry', {
+ characterId: currentCharacter.id,
+ keys: keysArray,
+ content: content,
+ priority,
+ caseSensitive: false
+ });
+
+ formDiv.remove();
+ await loadRoleplaySettings();
+ } catch (error) {
+ console.error('Failed to add World Info entry:', error);
+ alert(`Failed to add entry: ${error}`);
+ }
+ });
}
// Edit World Info entry
async function handleEditWorldInfoEntry(entry) {
- const keys = prompt('Edit keywords (comma-separated):', entry.keys.join(', '));
- if (keys === null) return;
+ const entryDiv = document.querySelector(`.worldinfo-entry[data-entry-id="${entry.id}"]`);
+ if (!entryDiv) return;
- const content = prompt('Edit content:', entry.content);
- if (content === null) return;
+ // Check if already editing
+ if (entryDiv.querySelector('.worldinfo-inline-edit')) return;
- const priorityStr = prompt('Edit priority:', entry.priority.toString());
- if (priorityStr === null) return;
- const priority = parseInt(priorityStr) || 0;
+ // Hide normal content
+ const header = entryDiv.querySelector('.worldinfo-entry-header');
+ const content = entryDiv.querySelector('.worldinfo-entry-content');
+ header.style.display = 'none';
+ content.style.display = 'none';
- try {
- const keysArray = keys.split(',').map(k => k.trim()).filter(k => k);
- await invoke('update_world_info_entry', {
- characterId: currentCharacter.id,
- entryId: entry.id,
- keys: keysArray,
- content: content.trim(),
- enabled: entry.enabled,
- priority,
- caseSensitive: entry.case_sensitive
- });
+ // Create inline edit form
+ const editForm = document.createElement('div');
+ editForm.className = 'worldinfo-inline-edit';
+ editForm.innerHTML = `
+
+
Edit Entry
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
- // Reload settings
- await loadRoleplaySettings();
- } catch (error) {
- console.error('Failed to update World Info entry:', error);
- alert(`Failed to update entry: ${error}`);
- }
+ entryDiv.appendChild(editForm);
+
+ // Focus first input
+ editForm.querySelector('.wi-edit-keys').focus();
+
+ // Handle cancel
+ editForm.querySelector('.wi-edit-cancel').addEventListener('click', () => {
+ header.style.display = '';
+ content.style.display = '';
+ editForm.remove();
+ });
+
+ // Handle save
+ editForm.querySelector('.wi-edit-save').addEventListener('click', async () => {
+ const keys = editForm.querySelector('.wi-edit-keys').value.trim();
+ const contentText = editForm.querySelector('.wi-edit-content').value.trim();
+ const priority = parseInt(editForm.querySelector('.wi-edit-priority').value) || 0;
+
+ if (!keys || !contentText) {
+ alert('Keywords and content are required');
+ return;
+ }
+
+ try {
+ const keysArray = keys.split(',').map(k => k.trim()).filter(k => k);
+ await invoke('update_world_info_entry', {
+ characterId: currentCharacter.id,
+ entryId: entry.id,
+ keys: keysArray,
+ content: contentText,
+ enabled: entry.enabled,
+ priority,
+ caseSensitive: entry.case_sensitive
+ });
+
+ await loadRoleplaySettings();
+ } catch (error) {
+ console.error('Failed to update World Info entry:', error);
+ alert(`Failed to update entry: ${error}`);
+ }
+ });
}
// Toggle World Info entry enabled state
@@ -2781,45 +2876,147 @@ function renderInstructionBlocks(instructions, isReadOnly) {
function addInstructionBlock() {
if (!currentEditingPreset) return;
- const name = prompt('Enter instruction block name:');
- if (!name || !name.trim()) return;
+ const listContainer = document.getElementById('preset-instructions-list');
- const content = prompt('Enter instruction block content:');
- if (!content || !content.trim()) return;
+ // Check if form already exists
+ if (document.getElementById('instruction-add-form')) return;
- // Generate ID and determine order
- const id = `inst_${Date.now()}`;
- const maxOrder = currentEditingPreset.instructions.length > 0
- ? Math.max(...currentEditingPreset.instructions.map(i => i.order))
- : 0;
+ // Create inline form
+ const formDiv = document.createElement('div');
+ formDiv.id = 'instruction-add-form';
+ formDiv.style.background = 'var(--bg-secondary)';
+ formDiv.style.border = '2px solid var(--accent)';
+ formDiv.style.borderRadius = '6px';
+ formDiv.style.padding = '12px';
+ formDiv.style.marginBottom = '8px';
- const newInstruction = {
- id,
- name: name.trim(),
- content: content.trim(),
- enabled: true,
- order: maxOrder + 1
- };
+ formDiv.innerHTML = `
+
+
Add Instruction Block
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
- currentEditingPreset.instructions.push(newInstruction);
+ listContainer.prepend(formDiv);
+ document.getElementById('inst-add-name').focus();
- // Re-render
- renderInstructionBlocks(currentEditingPreset.instructions, false);
+ // Handle cancel
+ document.getElementById('inst-add-cancel').addEventListener('click', () => {
+ formDiv.remove();
+ });
+
+ // Handle save
+ document.getElementById('inst-add-save').addEventListener('click', () => {
+ const name = document.getElementById('inst-add-name').value.trim();
+ const content = document.getElementById('inst-add-content').value.trim();
+
+ if (!name || !content) {
+ alert('Name and content are required');
+ return;
+ }
+
+ // Generate ID and determine order
+ const id = `inst_${Date.now()}`;
+ const maxOrder = currentEditingPreset.instructions.length > 0
+ ? Math.max(...currentEditingPreset.instructions.map(i => i.order))
+ : 0;
+
+ const newInstruction = {
+ id,
+ name,
+ content,
+ enabled: true,
+ order: maxOrder + 1
+ };
+
+ currentEditingPreset.instructions.push(newInstruction);
+ formDiv.remove();
+
+ // Re-render
+ renderInstructionBlocks(currentEditingPreset.instructions, false);
+ });
}
// Edit instruction block
function editInstruction(instruction) {
- const newName = prompt('Edit instruction block name:', instruction.name);
- if (newName === null) return;
+ // Find the instruction block div
+ const listContainer = document.getElementById('preset-instructions-list');
+ const blocks = Array.from(listContainer.children);
+ const blockDiv = blocks.find(el => {
+ const header = el.querySelector('[style*="cursor: pointer"]');
+ return header && header.textContent.includes(instruction.name);
+ });
- const newContent = prompt('Edit instruction block content:', instruction.content);
- if (newContent === null) return;
+ if (!blockDiv) return;
- instruction.name = newName.trim();
- instruction.content = newContent.trim();
+ // Check if already editing
+ if (blockDiv.querySelector('.instruction-edit-form')) return;
- // Re-render
- renderInstructionBlocks(currentEditingPreset.instructions, false);
+ // Hide original content
+ const header = blockDiv.querySelector('[style*="cursor: pointer"]');
+ const content = blockDiv.querySelector('.instruction-content');
+ header.style.display = 'none';
+ content.style.display = 'none';
+
+ // Create edit form
+ const editForm = document.createElement('div');
+ editForm.className = 'instruction-edit-form';
+ editForm.style.padding = '8px';
+ editForm.innerHTML = `
+
+
Edit Instruction Block
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ blockDiv.appendChild(editForm);
+ editForm.querySelector('.inst-edit-name').focus();
+
+ // Handle cancel
+ editForm.querySelector('.inst-edit-cancel').addEventListener('click', () => {
+ header.style.display = '';
+ content.style.display = '';
+ editForm.remove();
+ });
+
+ // Handle save
+ editForm.querySelector('.inst-edit-save').addEventListener('click', () => {
+ const newName = editForm.querySelector('.inst-edit-name').value.trim();
+ const newContent = editForm.querySelector('.inst-edit-content').value.trim();
+
+ if (!newName || !newContent) {
+ alert('Name and content are required');
+ return;
+ }
+
+ instruction.name = newName;
+ instruction.content = newContent;
+
+ // Re-render
+ renderInstructionBlocks(currentEditingPreset.instructions, false);
+ });
}
// Delete instruction block
diff --git a/src/styles.css b/src/styles.css
index 6632844..8813ad3 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -1855,6 +1855,41 @@ body.view-comfortable .message-content pre {
word-wrap: break-word;
}
+.worldinfo-edit-form,
+.worldinfo-inline-edit {
+ background: var(--bg-secondary);
+ border: 2px solid var(--accent);
+ border-radius: 8px;
+ padding: 16px;
+}
+
+.worldinfo-edit-form input,
+.worldinfo-edit-form textarea,
+.worldinfo-inline-edit input,
+.worldinfo-inline-edit textarea {
+ background: var(--bg-tertiary);
+ border: 1px solid var(--border);
+ border-radius: 6px;
+ padding: 8px;
+ color: var(--text-primary);
+ font-size: 13px;
+ font-family: inherit;
+}
+
+.worldinfo-edit-form input:focus,
+.worldinfo-edit-form textarea:focus,
+.worldinfo-inline-edit input:focus,
+.worldinfo-inline-edit textarea:focus {
+ outline: none;
+ border-color: var(--accent);
+}
+
+.worldinfo-edit-form textarea,
+.worldinfo-inline-edit textarea {
+ resize: vertical;
+ min-height: 80px;
+}
+
.header-left-controls {
display: flex;
gap: 8px;