Class AiMessageInput

java.lang.Object
com.vaadin.flow.component.Component
io.jmix.aichat.component.messageinput.AiMessageInput
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, com.vaadin.flow.component.BlurNotifier<AiMessageInput>, com.vaadin.flow.component.DetachNotifier, com.vaadin.flow.component.Focusable<AiMessageInput>, com.vaadin.flow.component.FocusNotifier<AiMessageInput>, com.vaadin.flow.component.HasElement, com.vaadin.flow.component.HasEnabled, com.vaadin.flow.component.HasSize, com.vaadin.flow.component.HasStyle, com.vaadin.flow.component.HasTheme, com.vaadin.flow.component.shared.HasPrefix, com.vaadin.flow.component.shared.HasSuffix, com.vaadin.flow.component.shared.HasThemeVariant<AiMessageInputVariant>, com.vaadin.flow.component.shared.HasTooltip, HasSubParts, Serializable, org.springframework.beans.factory.Aware, org.springframework.beans.factory.InitializingBean, org.springframework.context.ApplicationContextAware

@Tag("jmix-ai-message-input") @JsModule("./src/ai-chat/messageinput/jmix-ai-message-input.js") public class AiMessageInput extends com.vaadin.flow.component.Component implements com.vaadin.flow.component.Focusable<AiMessageInput>, com.vaadin.flow.component.HasSize, com.vaadin.flow.component.HasStyle, com.vaadin.flow.component.HasEnabled, com.vaadin.flow.component.shared.HasTooltip, com.vaadin.flow.component.shared.HasThemeVariant<AiMessageInputVariant>, com.vaadin.flow.component.shared.HasPrefix, com.vaadin.flow.component.shared.HasSuffix, HasSubParts, org.springframework.context.ApplicationContextAware, org.springframework.beans.factory.InitializingBean
Message Input allows users to author and send messages. The component displays an autoresizing text-area and a send button. While the application is generating a response (see setGenerating(boolean)) the send button becomes a stop button that fires a AiMessageInput.StopEvent.

Custom controls (e.g. an attach/context-menu button or a model selector) can be placed around the field via HasPrefix.setPrefixComponent(Component) / HasSuffix.setSuffixComponent(Component). The layout is adaptive: a single row while the text is short, reflowing the controls into a toolbar beneath the textarea once it grows past one line. AiMessageInputVariant.FIXED_TOOLBAR forces the toolbar layout at all times.

Use the AiMessageList component to show messages that users have sent.

See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
    Fired when the UploadManager rejects a file (too many, too large, or wrong type).
    static class 
    The stop event, fired when the user clicks the button while the input is in the generating state (see setGenerating(boolean)).
    static class 
    The submit event which is fired by AiMessageInput component.

    Nested classes/interfaces inherited from interface com.vaadin.flow.component.BlurNotifier

    com.vaadin.flow.component.BlurNotifier.BlurEvent<C extends com.vaadin.flow.component.Component>

    Nested classes/interfaces inherited from interface com.vaadin.flow.component.FocusNotifier

    com.vaadin.flow.component.FocusNotifier.FocusEvent<C extends com.vaadin.flow.component.Component>
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected List<String>
     
    protected List<String>
     
    protected org.springframework.context.ApplicationContext
     
    protected @Nullable com.vaadin.flow.component.upload.UploadButton
     
    protected @Nullable com.vaadin.flow.component.upload.UploadFileList
     
    protected List<com.vaadin.flow.component.ai.common.AIAttachment>
     
    protected boolean
     
    protected EnterAction
     
    protected boolean
     
     
    protected int
     
    protected long
     
    protected int
     
    protected boolean
     
    protected @Nullable com.vaadin.flow.component.upload.UploadManager
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates a new message input component.
    AiMessageInput(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.SubmitEvent> listener)
    Creates a new message input component with the provided listener that gets invoked when the user submits a new message.
  • Method Summary

    Modifier and Type
    Method
    Description
    com.vaadin.flow.shared.Registration
    addAttachmentRejectedListener(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.AttachmentRejectedEvent> listener)
    Adds a listener notified when a file the user offered is rejected.
    com.vaadin.flow.shared.Registration
    addStopListener(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.StopEvent> listener)
    Adds a listener that is called when the user clicks the stop button (shown instead of send while isGenerating() is true).
    com.vaadin.flow.shared.Registration
    addSubmitListener(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.SubmitEvent> listener)
    Adds a listener that is called when the user submits the value of the input field, which can be obtained with AiMessageInput.SubmitEvent.getValue().
    void
     
    protected void
    Applies the accessible name (aria-label) to the icon-only attach (paperclip) button from the current i18n, if both the button and a translated value are available.
    protected void
    Pushes the file-count, size and type restrictions onto the upload transport.
    protected void
    Builds a UploadFileListI18N from the Messages bean (remove-button label and the tooManyFiles/fileIsTooBig/incorrectFileType validation errors) and applies it to the attachment list, if the list exists and the Messages bean is reachable.
    void
    Removes all pending attachments (and clears the upload UI, once wired).
    protected void
    Clears the pending attachments after an effective submit only.
    protected void
    Schedules clearAttachments() to run at the end of the current server round-trip instead of immediately.
    protected void
    Tears the upload transport down and clears whatever it had buffered.
    protected void
    Creates the upload transport and applies the current attachment configuration to it.
    protected Optional<com.vaadin.flow.component.Component>
    findSlotSubPart(com.vaadin.flow.component.Component slotComponent, String name)
    Resolves an id against a single slot component: the component itself when its own id matches, otherwise a descendant of it.
     
     
    List<com.vaadin.flow.component.ai.common.AIAttachment>
    Gets the files the user has attached but not yet submitted.
     
    @Nullable com.vaadin.flow.component.Component
     
    @Nullable com.vaadin.flow.component.Component
     
    Gets the internationalization object previously set for this component.
    int
     
    long
     
    int
     
    @Nullable Object
    Makes a component declared with an id in the header / footer slot reachable by UiComponentUtils.findComponent — and thus injectable with @ViewComponent — like a top-level component.
    protected void
    handleUploadedAttachment(String name, String mimeType, byte[] data)
    Buffers a completed upload as an AIAttachment, mirroring the client file list: every completed upload appends, including a re-upload of an already-buffered name (the client keeps both chips at this point).
    protected void
    Registers the internal listeners.
    protected void
    Resolves the localization from the message bundle.
    boolean
    Whether the attach affordance (paperclip, drag-and-drop, chips) is shown.
    boolean
     
    boolean
     
    protected void
    onAttach(com.vaadin.flow.component.AttachEvent attachEvent)
     
    protected void
    Removes the oldest buffered attachment with the given file name — one entry per event, since the client reports one removed chip at a time (by name only).
    void
    Restricts attachments to the given file extensions.
    void
    Restricts attachments to the given MIME types.
    void
    setApplicationContext(org.springframework.context.ApplicationContext applicationContext)
     
    void
    setAttachmentsEnabled(boolean attachmentsEnabled)
    Sets whether the attach affordance is shown.
    void
    Sets what the Enter key does.
    void
    setFooterComponent(@Nullable com.vaadin.flow.component.Component component)
    Sets a component into the footer slot — the band below the input box, inside the composer.
    void
    setGenerating(boolean generating)
    Sets whether a response is currently being generated.
    void
    setHeaderComponent(@Nullable com.vaadin.flow.component.Component component)
    Sets a component into the header slot — the band above the input box, inside the composer.
    void
    Sets the internationalization object for this component.
    void
    setMaxFiles(int maxFiles)
    Sets the maximum number of files that can be attached to one message.
    void
    setMaxFileSize(long maxFileSize)
    Sets the maximum size of a single attachment.
    void
    setMaxRows(int maxRows)
    Sets the maximum number of visible text rows before the text-area scrolls internally.
    void
    setUploadDropZoneEnabled(boolean uploadDropZoneEnabled)
    Sets whether files may be attached by dropping them on the composer.

    Methods inherited from class com.vaadin.flow.component.Component

    addListener, bindVisible, findAncestor, fireEvent, from, get, getChildren, getElement, getEventBus, getId, getListeners, getLocale, getParent, getTestId, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getUI, hasListener, isAttached, isTemplateMapped, isVisible, onDetach, onEnabledStateChanged, removeFromParent, scrollIntoView, scrollIntoView, set, setElement, setId, setTestId, setVisible, whenAttached

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface com.vaadin.flow.component.AttachNotifier

    addAttachListener

    Methods inherited from interface com.vaadin.flow.component.BlurNotifier

    addBlurListener

    Methods inherited from interface com.vaadin.flow.component.DetachNotifier

    addDetachListener

    Methods inherited from interface com.vaadin.flow.component.Focusable

    addFocusShortcut, blur, focus, focus, getTabIndex, setTabIndex

    Methods inherited from interface com.vaadin.flow.component.FocusNotifier

    addFocusListener

    Methods inherited from interface com.vaadin.flow.component.HasElement

    getElement

    Methods inherited from interface com.vaadin.flow.component.HasEnabled

    bindEnabled, isEnabled, setEnabled

    Methods inherited from interface com.vaadin.flow.component.shared.HasPrefix

    getPrefixComponent, setPrefixComponent

    Methods inherited from interface com.vaadin.flow.component.HasSize

    bindHeight, bindWidth, getHeight, getHeightUnit, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getWidth, getWidthUnit, setHeight, setHeight, setHeightFull, setMaxHeight, setMaxHeight, setMaxWidth, setMaxWidth, setMinHeight, setMinHeight, setMinWidth, setMinWidth, setSizeFull, setSizeUndefined, setWidth, setWidth, setWidthFull

    Methods inherited from interface com.vaadin.flow.component.HasStyle

    addClassName, addClassNames, bindClassName, bindClassNames, getClassName, getClassNames, getStyle, hasClassName, removeClassName, removeClassNames, setClassName, setClassName

    Methods inherited from interface com.vaadin.flow.component.shared.HasSuffix

    getSuffixComponent, setSuffixComponent

    Methods inherited from interface com.vaadin.flow.component.HasTheme

    addThemeName, addThemeNames, bindThemeName, bindThemeNames, getThemeName, getThemeNames, hasThemeName, removeThemeName, removeThemeNames, setThemeName, setThemeName

    Methods inherited from interface com.vaadin.flow.component.shared.HasThemeVariant

    addThemeVariants, bindThemeVariant, bindThemeVariants, removeThemeVariants, setThemeVariant, setThemeVariants, setThemeVariants

    Methods inherited from interface com.vaadin.flow.component.shared.HasTooltip

    getTooltip, setTooltipMarkdown, setTooltipText
  • Field Details

    • applicationContext

      protected org.springframework.context.ApplicationContext applicationContext
    • i18n

      protected AiMessageInputI18n i18n
    • maxRows

      protected int maxRows
    • enterAction

      protected EnterAction enterAction
    • generating

      protected boolean generating
    • attachmentsEnabled

      protected boolean attachmentsEnabled
    • maxFiles

      protected int maxFiles
    • maxFileSize

      protected long maxFileSize
    • acceptedMimeTypes

      protected List<String> acceptedMimeTypes
    • acceptedFileExtensions

      protected List<String> acceptedFileExtensions
    • uploadDropZoneEnabled

      protected boolean uploadDropZoneEnabled
    • attachments

      protected List<com.vaadin.flow.component.ai.common.AIAttachment> attachments
    • uploadManager

      protected @Nullable com.vaadin.flow.component.upload.UploadManager uploadManager
    • attachButton

      protected @Nullable com.vaadin.flow.component.upload.UploadButton attachButton
    • attachmentList

      protected @Nullable com.vaadin.flow.component.upload.UploadFileList attachmentList
  • Constructor Details

    • AiMessageInput

      public AiMessageInput()
      Creates a new message input component.
    • AiMessageInput

      public AiMessageInput(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.SubmitEvent> listener)
      Creates a new message input component with the provided listener that gets invoked when the user submits a new message.
      Parameters:
      listener - the submit event listener
      See Also:
  • Method Details

    • initComponent

      protected void initComponent()
      Registers the internal listeners. Called from the constructor.
    • addSubmitListener

      public com.vaadin.flow.shared.Registration addSubmitListener(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.SubmitEvent> listener)
      Adds a listener that is called when the user submits the value of the input field, which can be obtained with AiMessageInput.SubmitEvent.getValue().

      The event is fired when clicking the send button or pressing the Enter key (subject to setEnterAction(EnterAction)). It is not fired while the input is generating.

      Parameters:
      listener - the listener
      Returns:
      registration for removal of the listener
    • addStopListener

      public com.vaadin.flow.shared.Registration addStopListener(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.StopEvent> listener)
      Adds a listener that is called when the user clicks the stop button (shown instead of send while isGenerating() is true).
      Parameters:
      listener - the listener
      Returns:
      registration for removal of the listener
    • addAttachmentRejectedListener

      public com.vaadin.flow.shared.Registration addAttachmentRejectedListener(com.vaadin.flow.component.ComponentEventListener<AiMessageInput.AttachmentRejectedEvent> listener)
      Adds a listener notified when a file the user offered is rejected.
      Parameters:
      listener - the listener to add
      Returns:
      a registration for removing the listener
    • setGenerating

      public void setGenerating(boolean generating)
      Sets whether a response is currently being generated. While true the send button is replaced by a stop button (clicking it fires AiMessageInput.StopEvent) and message submission is suppressed; the text-area stays editable.
      Parameters:
      generating - true to show the stop affordance and suppress submit
    • isGenerating

      public boolean isGenerating()
      Returns:
      whether the input is in the generating (stop) state
    • setMaxRows

      public void setMaxRows(int maxRows)
      Sets the maximum number of visible text rows before the text-area scrolls internally. Defaults to 10.
      Parameters:
      maxRows - the maximum number of visible rows
    • getMaxRows

      public int getMaxRows()
      Returns:
      the maximum number of visible text rows (default 10)
    • setEnterAction

      public void setEnterAction(EnterAction enterAction)
      Sets what the Enter key does. Defaults to EnterAction.SEND.
      Parameters:
      enterAction - the Enter-key behavior, not null
    • getEnterAction

      public EnterAction getEnterAction()
      Returns:
      the current Enter-key behavior (never null)
    • getI18n

      public AiMessageInputI18n getI18n()
      Gets the internationalization object previously set for this component.

      NOTE: Updating the instance that is returned from this method will not update the component if not set again using setI18n(AiMessageInputI18n).

      Returns:
      the i18n object, resolved from the message bundle when the component was created and replaced by every setI18n(AiMessageInputI18n) since
    • setI18n

      public void setI18n(AiMessageInputI18n i18n)
      Sets the internationalization object for this component. It enables you to customize and translate the language used in the message input.

      Note: updating the object properties after setting the i18n will not update the component. To make the changes effective, you need to set the updated object again.

      If the attach affordance is already enabled (see setAttachmentsEnabled(boolean)), this also re-applies the paperclip button's accessible name from AiMessageInputI18n.getAttach() and the file list's labels, covering the case where attachments were enabled before this method was first called.

      Parameters:
      i18n - the i18n object, not null
    • setHeaderComponent

      public void setHeaderComponent(@Nullable com.vaadin.flow.component.Component component)
      Sets a component into the header slot — the band above the input box, inside the composer. Passing null clears the slot.
      Parameters:
      component - the component, or null to clear
    • getHeaderComponent

      public @Nullable com.vaadin.flow.component.Component getHeaderComponent()
      Returns:
      the component in the header slot, or null if empty
    • setFooterComponent

      public void setFooterComponent(@Nullable com.vaadin.flow.component.Component component)
      Sets a component into the footer slot — the band below the input box, inside the composer. Passing null clears the slot.
      Parameters:
      component - the component, or null to clear
    • getFooterComponent

      public @Nullable com.vaadin.flow.component.Component getFooterComponent()
      Returns:
      the component in the footer slot, or null if empty
    • getSubPart

      public @Nullable Object getSubPart(String name)
      Makes a component declared with an id in the header / footer slot reachable by UiComponentUtils.findComponent — and thus injectable with @ViewComponent — like a top-level component. The prefix / suffix slots already have this through HasPrefix / HasSuffix, so they are not re-handled here.
      Specified by:
      getSubPart in interface HasSubParts
      Parameters:
      name - the component id to find
      Returns:
      the matching slot component or descendant, or null if none matches
    • findSlotSubPart

      protected Optional<com.vaadin.flow.component.Component> findSlotSubPart(com.vaadin.flow.component.Component slotComponent, String name)
      Resolves an id against a single slot component: the component itself when its own id matches, otherwise a descendant of it.
      Parameters:
      slotComponent - the slot component to search
      name - the component id to find
      Returns:
      the matching component, or an empty Optional
    • setApplicationContext

      public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws org.springframework.beans.BeansException
      Specified by:
      setApplicationContext in interface org.springframework.context.ApplicationContextAware
      Throws:
      org.springframework.beans.BeansException
    • afterPropertiesSet

      public void afterPropertiesSet()
      Specified by:
      afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
    • initI18n

      protected void initI18n()
      Resolves the localization from the message bundle. Runs from afterPropertiesSet(), after the application context is injected.
    • getAttachments

      public List<com.vaadin.flow.component.ai.common.AIAttachment> getAttachments()
      Gets the files the user has attached but not yet submitted.
      Returns:
      an unmodifiable, non-null snapshot of the pending attachments
    • clearAttachments

      public void clearAttachments()
      Removes all pending attachments (and clears the upload UI, once wired).
    • deferAttachmentsClear

      protected void deferAttachmentsClear()
      Schedules clearAttachments() to run at the end of the current server round-trip instead of immediately. Flow adds a separate DOM listener per addSubmitListener call (see ComponentEventBus; there is no per-event-type de-duplication), so a single client submit constructs one AiMessageInput.SubmitEvent per registered listener. Clearing synchronously here would empty the buffer between those constructions, and an application submit listener registered after this one would then snapshot an already-cleared buffer. Deferring the clear until after all listeners have taken their snapshots lets every submit listener observe the pending attachments regardless of listener order, and without relying on push (so it also works in a background tab).
    • clearAttachmentsOnSubmit

      protected void clearAttachmentsOnSubmit(AiMessageInput.SubmitEvent event)
      Clears the pending attachments after an effective submit only. A submit with nothing to send — a blank value and no attachment — or one that raced the generating state before the client learned it, is ignored by consumers (see AiChat#send) — clearing on such a submit would silently destroy attachments that were never sent, so the buffer and the file-list chips survive for the next attempt. The conjunction mirrors that consumer's own guard: an attachment alone is a message, so a blank submit carrying one is effective.
      Parameters:
      event - the submit event to judge
    • isAttachmentsEnabled

      public boolean isAttachmentsEnabled()
      Whether the attach affordance (paperclip, drag-and-drop, chips) is shown. Off by default; enabling it wires the upload transport.
      Returns:
      true if attachments are enabled
    • setAttachmentsEnabled

      public void setAttachmentsEnabled(boolean attachmentsEnabled)
      Sets whether the attach affordance is shown. Enabling it creates the upload transport, which needs a UI, so for a detached component that is deferred to attach.
      Parameters:
      attachmentsEnabled - true to enable attachments
    • onAttach

      protected void onAttach(com.vaadin.flow.component.AttachEvent attachEvent)
      Overrides:
      onAttach in class com.vaadin.flow.component.Component
    • enableAttachments

      protected void enableAttachments()
      Creates the upload transport and applies the current attachment configuration to it. Runs on enabling attachments, or on attach when the component was detached then.
    • applyAttachAriaLabel

      protected void applyAttachAriaLabel()
      Applies the accessible name (aria-label) to the icon-only attach (paperclip) button from the current i18n, if both the button and a translated value are available.

      Called both when the button is created (enableAttachments()) and whenever setI18n(AiMessageInputI18n) is called afterwards, since the two can happen in either order depending on how the component is configured.

    • applyAttachmentListI18n

      protected void applyAttachmentListI18n()
      Builds a UploadFileListI18N from the Messages bean (remove-button label and the tooManyFiles/fileIsTooBig/incorrectFileType validation errors) and applies it to the attachment list, if the list exists and the Messages bean is reachable.

      Called both when the list is created (enableAttachments()) and whenever setI18n(AiMessageInputI18n) is called afterwards, for the same reason as applyAttachAriaLabel().

    • disableAttachments

      protected void disableAttachments()
      Tears the upload transport down and clears whatever it had buffered.
    • applyAttachmentConfig

      protected void applyAttachmentConfig()
      Pushes the file-count, size and type restrictions onto the upload transport. A no-op while there is none, the values being re-applied when one is created.
    • getMaxFiles

      public int getMaxFiles()
      Returns:
      the maximum number of files that can be attached to one message
    • setMaxFiles

      public void setMaxFiles(int maxFiles)
      Sets the maximum number of files that can be attached to one message.
      Parameters:
      maxFiles - the maximum file count
    • getMaxFileSize

      public long getMaxFileSize()
      Returns:
      the maximum size of a single attachment, in bytes
    • setMaxFileSize

      public void setMaxFileSize(long maxFileSize)
      Sets the maximum size of a single attachment.
      Parameters:
      maxFileSize - the maximum size, in bytes
    • getAcceptedMimeTypes

      public List<String> getAcceptedMimeTypes()
      Returns:
      an unmodifiable view of the accepted MIME types, empty when any type is accepted
    • setAcceptedMimeTypes

      public void setAcceptedMimeTypes(String... mimeTypes)
      Restricts attachments to the given MIME types. Passing none accepts any type.
      Parameters:
      mimeTypes - the accepted MIME types, e.g. "image/*"
    • getAcceptedFileExtensions

      public List<String> getAcceptedFileExtensions()
      Returns:
      an unmodifiable view of the accepted file extensions, empty when any is accepted
    • setAcceptedFileExtensions

      public void setAcceptedFileExtensions(String... extensions)
      Restricts attachments to the given file extensions. Passing none accepts any extension.
      Parameters:
      extensions - the accepted extensions, e.g. ".png"
    • isUploadDropZoneEnabled

      public boolean isUploadDropZoneEnabled()
      Returns:
      true if files may be attached by dropping them on the composer
    • setUploadDropZoneEnabled

      public void setUploadDropZoneEnabled(boolean uploadDropZoneEnabled)
      Sets whether files may be attached by dropping them on the composer. Enabled by default; the paperclip stays available either way.
      Parameters:
      uploadDropZoneEnabled - true to accept dropped files
    • handleUploadedAttachment

      protected void handleUploadedAttachment(String name, String mimeType, byte[] data)
      Buffers a completed upload as an AIAttachment, mirroring the client file list: every completed upload appends, including a re-upload of an already-buffered name (the client keeps both chips at this point). The client then completes the replace-by-name contract by pruning the stale same-name chip, which arrives as a regular file-remove and drops the oldest buffered entry in removeBufferedAttachment(String). The UploadManager's in-memory handler delegates here.
      Parameters:
      name - the uploaded file's name
      mimeType - the uploaded file's content type
      data - the uploaded file's content
    • removeBufferedAttachment

      protected void removeBufferedAttachment(String name)
      Removes the oldest buffered attachment with the given file name — one entry per event, since the client reports one removed chip at a time (by name only). While a same-name re-upload transiently duplicates a name (see handleUploadedAttachment(String, String, byte[])), the oldest entry is the replaced one. The UploadManager's file-removed listener delegates here.
      Parameters:
      name - the file name reported as removed