All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.flow.component.messages.MessageListItem Maven / Gradle / Ivy

There is a newer version: 24.5.5
Show newest version
/*
 * Copyright 2000-2024 Vaadin Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.vaadin.flow.component.messages;

import java.io.Serializable;
import java.net.URI;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.vaadin.flow.internal.NodeOwner;
import com.vaadin.flow.internal.StateTree;
import com.vaadin.flow.server.AbstractStreamResource;
import com.vaadin.flow.server.Command;
import com.vaadin.flow.server.StreamRegistration;
import com.vaadin.flow.server.StreamResourceRegistry;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.shared.Registration;

/**
 * Item to render as a message component inside a {@link MessageList}.
 *
 * @author Vaadin Ltd.
 * @see MessageList#setItems(Collection)
 */
public class MessageListItem implements Serializable {

    private MessageList host;

    private String text;
    private Instant time;

    private String userName;
    private String userAbbreviation;
    private String userImage;
    private Integer userColorIndex;

    private StreamRegistration resourceRegistration;
    private Registration pendingRegistration;
    private Command pendingHandle;
    private AbstractStreamResource imageResource;

    private Set themeNames = new LinkedHashSet<>();
    private Set classNames = new LinkedHashSet<>();

    /**
     * Creates an empty message list item. Use the setter methods to configure
     * what will be displayed in the message.
     */
    public MessageListItem() {
    }

    /**
     * Creates a message list item with the provided text, which will be
     * displayed as plain text in the message body.
     *
     * @param text
     *            the text content of the message
     * @see #setText(String)
     */
    public MessageListItem(String text) {
        this.text = text;
    }

    /**
     * Creates a message list item with the provided text content, time and user
     * name.
     * 

* The text will be rendered as plain text in the message body. The time and * user name will also be displayed in the message component. The user name * is also used in the message's avatar. * * @param text * the text content of the message * @param time * the time of sending the message * @param userName * the user name of the message sender * @see #setText(String) * @see #setTime(Instant) * @see #setUserName(String) */ public MessageListItem(String text, Instant time, String userName) { this(text); this.time = time; this.userName = userName; } /** * Creates a message list item with the provided text content, time and user * name. *

* The text will be rendered as plain text in the message body. The time and * user name will also be displayed in the message component. The user image * will be displayed in an avatar in the message. * * @param text * the text content of the message * @param time * the time of sending the message * @param userName * the user name of the message sender * @param userImage * the URL of the message sender's image * @see #setText(String) * @see #setTime(Instant) * @see #setUserName(String) * @see #setUserImage(String) */ public MessageListItem(String text, Instant time, String userName, String userImage) { this(text, time, userName); this.userImage = userImage; } /** * Gets the text content of the message. * * @return the message's text content, or {@code null} if none is set */ public String getText() { return text; } /** * Sets the text content of the message. It will be rendered as plain text * in the message body. * * @param text * the message's text content to set, or {@code null} to remove * the content */ public void setText(String text) { this.text = text; propsChanged(); } /** * Gets the time of sending the message. * * @return the time of the message, or {@code null} if none is set */ @JsonSerialize(using = ToStringSerializer.class) public Instant getTime() { return time; } /** * Sets the time of sending the message. It will be displayed in the message * component. * * @param time * the time of the message to set, or {@code null} to remove the * time */ public void setTime(Instant time) { this.time = time; propsChanged(); } /** * Gets the user name of the message sender. * * @return the message sender's user name, or {@code null} if none is set */ public String getUserName() { return userName; } /** * Sets the user name of the message sender. It will be displayed in the * message component and used in the message's avatar. *

* In the avatar, the user name is presented in a tooltip on hover. It will * be also used to generate an abbreviation that is displayed as the avatar * content, when no {@link #setUserImage(String)} image} or * {@link #setUserAbbreviation(String)} abbreviation} is explicitly defined. * * @param userName * the message sender's user name, or {@code null} to remove the * user name */ public void setUserName(String userName) { this.userName = userName; propsChanged(); } /** * Gets the abbreviation of the message sender. * * @return the message sender's abbreviation, or {@code null} if none is set */ @JsonProperty("userAbbr") public String getUserAbbreviation() { return userAbbreviation; } /** * Sets the abbreviation of the message sender. It will be used in the * message's avatar, when no {@link #setUserImage(String)} image} is * defined. * * @param userAbbreviation * the message sender's abbreviation, or {@code null} to remove * the abbreviation */ public void setUserAbbreviation(String userAbbreviation) { this.userAbbreviation = userAbbreviation; propsChanged(); } /** * Gets the URL to the message sender's image. *

* If the image is set as a stream resource with * {@link MessageListItem#setUserImageResource(AbstractStreamResource)}, * this method will return a URL that is generated for that resource. * * @return the URL to the message sender's image, or {@code null} if none is * set */ @JsonProperty("userImg") public String getUserImage() { return userImage; } /** * Sets the URL to the message sender's image. The image be displayed in an * avatar in the message component. *

* Setting the image with this method resets the image resource provided * with {@link MessageListItem#setUserImageResource(AbstractStreamResource)} * * @param userImage * the URL to the message sender's image, or {@code null} to * remove the image * @see MessageListItem#setUserImageResource(AbstractStreamResource) */ public void setUserImage(String userImage) { unsetResource(); this.userImage = userImage; propsChanged(); } /** * Gets the color index of the message sender. * * @return the color index, or {@code null} if none is set */ public Integer getUserColorIndex() { return userColorIndex; } /** * Sets the color index of the message sender. It's used in the avatar that * is displayed in the message component. *

* The color index defines which color will be used for the border of the * avatar. Color index N applies CSS variable {@code --vaadin-user-color-N} * to the border. * * @param userColorIndex * the color index to set, or {@code null} to remove it */ public void setUserColorIndex(Integer userColorIndex) { this.userColorIndex = userColorIndex; propsChanged(); } /* * The following theme-related methods are copied from the HasTheme * interface, because the interface is compatible only with components. For * more detailed reasoning, see the discussion in: * https://github.com/vaadin/flow-components/pull/979#discussion_r634097080 */ /** * Adds one or more theme names to this message. Multiple theme names can be * specified by using multiple parameters. * * @param themeNames * the theme name or theme names to be added to the message */ public void addThemeNames(String... themeNames) { this.themeNames.addAll(Arrays.asList(themeNames)); propsChanged(); } /** * Removes one or more theme names from this message. Multiple theme names * can be specified by using multiple parameters. * * @param themeNames * the theme name or theme names to be removed from the message */ public void removeThemeNames(String... themeNames) { this.themeNames.removeAll(Arrays.asList(themeNames)); propsChanged(); } /** * Checks if the message has the given theme name. * * @param themeName * the theme name to check for * @return true if the message has the given theme name, * false otherwise */ public boolean hasThemeName(String themeName) { return themeNames.contains(themeName); } // Used only for Jackson serialization @JsonGetter private String getTheme() { if (themeNames.isEmpty()) { return null; } else { return themeNames.stream().collect(Collectors.joining(" ")); } } /** * Adds one or more class names to this item. Multiple class names can be * specified by using multiple parameters. * * @param classNames * the class name or class names to be added to the item */ public void addClassNames(String... classNames) { this.classNames.addAll(Arrays.asList(classNames)); propsChanged(); } /** * Removes one or more class names from this item. Multiple class names can * be specified by using multiple parameters. * * @param classNames * the class name or class names to be removed from the item */ public void removeClassNames(String... classNames) { this.classNames.removeAll(Arrays.asList(classNames)); propsChanged(); } /** * Checks if the message has the given class name. * * @param className * the class name to check for * @return true if the message has the given class name, * false otherwise */ public boolean hasClassName(String className) { return classNames.contains(className); } // Used only for Jackson serialization @JsonGetter private String getClassName() { if (classNames.isEmpty()) { return null; } else { return classNames.stream().collect(Collectors.joining(" ")); } } /** * Gets the image resource of the message sender's avatar. * * @return the image resource value, or {@code null} if the image has not * been set, or if the image is set with a URL by using * {@link MessageListItem#setUserImage(String)} */ @JsonIgnore public AbstractStreamResource getUserImageResource() { return imageResource; } /** * Sets the image for the message sender's avatar. *

* Setting the image as a resource with this method overrides the image URL * set with {@link MessageListItem#setUserImage(String)}. * * @param resource * the image resource, or {@code null} to remove the resource * @see MessageListItem#setUserImage(String) */ public void setUserImageResource(AbstractStreamResource resource) { imageResource = resource; if (resource == null) { unsetResource(); return; } // The following is the copy of functionality from the // ElementAttributeMap and AvatarGroupItem. doSetResource(resource); if (getHost() != null && getHost().getElement().getNode().isAttached()) { registerResource(resource); } else { deferRegistration(resource); } propsChanged(); } private void doSetResource(AbstractStreamResource resource) { final URI targetUri; if (VaadinSession.getCurrent() != null) { final StreamResourceRegistry resourceRegistry = VaadinSession .getCurrent().getResourceRegistry(); targetUri = resourceRegistry.getTargetURI(resource); } else { targetUri = StreamResourceRegistry.getURI(resource); } this.userImage = targetUri.toASCIIString(); } private void unregisterResource() { StreamRegistration registration = resourceRegistration; Registration handle = pendingRegistration; if (handle != null) { handle.remove(); } if (registration != null) { registration.unregister(); } this.userImage = null; } private void deferRegistration(AbstractStreamResource resource) { if (pendingRegistration != null) { return; } pendingHandle = () -> { doSetResource(resource); registerResource(resource); }; if (getHost() != null) { attachPendingRegistration(pendingHandle); pendingHandle = null; } } private void attachPendingRegistration(Command pendingHandle) { if (getHost().getElement().getNode().isAttached()) { pendingHandle.execute(); return; } Registration handle = getHost().getElement().getNode() // Do not convert to lambda .addAttachListener(pendingHandle); pendingRegistration = handle; } private void registerResource(AbstractStreamResource resource) { assert resourceRegistration == null; StreamRegistration registration = getSession().getResourceRegistry() .registerResource(resource); resourceRegistration = registration; Registration handle = pendingRegistration; if (handle != null) { handle.remove(); } pendingRegistration = getHost().getElement().getNode() .addDetachListener( // Do not convert to lambda new Command() { @Override public void execute() { MessageListItem.this.unsetResource(); } }); } private void unsetResource() { imageResource = null; StreamRegistration registration = resourceRegistration; Optional resource = Optional.empty(); if (registration != null) { resource = Optional.ofNullable(registration.getResource()); } unregisterResource(); resource.ifPresent(this::deferRegistration); } private VaadinSession getSession() { NodeOwner owner = getHost().getElement().getNode().getOwner(); assert owner instanceof StateTree; return ((StateTree) owner).getUI().getSession(); } private void propsChanged() { if (getHost() != null) { getHost().scheduleItemsUpdate(); } } void setHost(MessageList host) { this.host = host; if (pendingHandle != null) { attachPendingRegistration(pendingHandle); pendingHandle = null; } } @JsonIgnore MessageList getHost() { return host; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy