Feat: Improve multiline input handling in popups (#4756) * feat: improve multiline input handling in popups - Added Ctrl+Enter requirement for submission in multiline input popups to prevent accidental sends - Exported PopupUtils class for external use * refactor: remove redundant higher/different rows from input popups - Removed rows: 2 from callGenericPopup calls where default behavior is sufficient - Increased rows from 2 to 4 in caption extension for better multiline input experience
Signed| @@ -7267,7 +7267,7 @@ export function setUserName(value, { toastPersonaNameChange = true } = {}) { | ||
| 7267 | 7267 | |
| 7268 | 7268 | async function doOnboarding(avatarId) { |
| 7269 | 7269 | const template = $('#onboarding_template .onboarding'); |
| 7270 | 7270 | let userName = await callGenericPopup(template, POPUP_TYPE.INPUT, currentUser?.name || name1, { rows: 2, wider: true, cancelButton: false }); |
| 7271 | 7271 | |
| 7272 | 7272 | if (userName) { |
| 7273 | 7273 | userName = String(userName).replace('\n', ' '); |
| @@ -315,7 +315,7 @@ async function captionMultimodal(base64Img, externalPrompt) { | ||
| 315 | 315 | let prompt = externalPrompt || extension_settings.caption.prompt || PROMPT_DEFAULT; |
| 316 | 316 | |
| 317 | 317 | if (!externalPrompt && extension_settings.caption.prompt_ask) { |
| 318 | 318 | const customPrompt = await callGenericPopup('Enter a comment or question:', POPUP_TYPE.INPUT, prompt, { rows: 24 }); |
| 319 | 319 | if (!customPrompt) { |
| 320 | 320 | throw new Error('User aborted the caption sending.'); |
| 321 | 321 | } |
| @@ -286,7 +286,7 @@ async function createConnectionProfile(forceName = null) { | ||
| 286 | 286 | }); |
| 287 | 287 | const isNameTaken = (n) => extension_settings.connectionManager.profiles.some(p => p.name === n); |
| 288 | 288 | const suggestedName = getUniqueName(collapseSpaces(`${profile.api ?? ''} ${profile.model ?? ''} - ${profile.preset ?? ''}`), isNameTaken); |
| 289 | 289 | let name = forceName ?? await callGenericPopup(template, POPUP_TYPE.INPUT, suggestedName, { rows: 2 }); |
| 290 | 290 | // If it's cancelled, it will be false |
| 291 | 291 | if (!name) { |
| 292 | 292 | return null; |
| @@ -607,7 +607,6 @@ async function renderDetailsContent(detailsContent) { | ||
| 607 | 607 | }, {}); |
| 608 | 608 | const template = $(await renderExtensionTemplateAsync(MODULE_NAME, 'edit', { name: profile.name, settings })); |
| 609 | 609 | let newName = await callGenericPopup(template, POPUP_TYPE.INPUT, profile.name, { |
| 610 | - rows: 2, | |
| 611 | 610 | customButtons: [{ |
| 612 | 611 | text: t`Save and Update`, |
| 613 | 612 | classes: ['popup-button-ok'], |
| @@ -461,6 +461,13 @@ export class Popup { | ||
| 461 | 461 | if (input instanceof HTMLInputElement && !shouldSendOnEnter()) |
| 462 | 462 | return; |
| 463 | 463 | |
| 464 | + // If this is a multiline input popup, we should still not simply send on enter, that'd be weird. | |
| 465 | + // Let's still make it possible if CTRL is toggled though | |
| 466 | + if ((textarea instanceof HTMLTextAreaElement || input instanceof HTMLInputElement) | |
| 467 | + && !evt.ctrlKey && this.mainInput.rows > 1) { | |
| 468 | + return; | |
| 469 | + } | |
| 470 | + | |
| 464 | 471 | evt.preventDefault(); |
| 465 | 472 | evt.stopPropagation(); |
| 466 | 473 | const result = Number(document.activeElement.getAttribute('data-result') ?? this.defaultResult); |
| @@ -688,7 +695,7 @@ export class Popup { | ||
| 688 | 695 | }; |
| 689 | 696 | } |
| 690 | 697 | |
| 691 | 698 | export class PopupUtils { |
| 692 | 699 | /** |
| 693 | 700 | * Builds popup content with header and text below |
| 694 | 701 | * |
| @@ -528,7 +528,7 @@ class YouTubeScraper { | ||
| 528 | 528 | async scrape() { |
| 529 | 529 | let lang = ''; |
| 530 | 530 | const template = $(await renderExtensionTemplateAsync('attachments', 'youtube-scrape', {})); |
| 531 | 531 | const videoUrl = await callGenericPopup(template, POPUP_TYPE.INPUT, '', { wide: false, large: false, okButton: 'Scrape', cancelButton: 'Cancel', rows: 2 }); |
| 532 | 532 | |
| 533 | 533 | template.find('input[name="youtubeLanguageCode"]').on('input', function () { |
| 534 | 534 | lang = String($(this).val()).trim(); |