メッセージコンポーネント

    Messages Reactコンポーネントは、Messagesコンポーネントを表します。

    メッセージコンポーネント

    以下のコンポーネントが含まれています。

    • Messages - メインのメッセージコンテナ
    • Message - 単一のメッセージ要素
    • MessagesTitle - ひとつのメッセージのタイトル要素

    メッセージのプロパティ

    PropTypeDefaultDescription
    <Messages> properties
    initbooleantrueInitializes Messages component
    newMessagesFirstbooleanfalseEnable if you want to use new messages on top, instead of having them on bottom
    scrollMessagesbooleantrueEnable/disable messages autoscrolling when adding new message
    scrollMessagesOnEdgebooleantrueIf enabled then messages autoscrolling will happen only when user is on top/bottom of the messages view
    typingbooleanfalseAllows to display/toggle typing message indicator
    <Message> properties
    typestringsentMessage type: sent (default) or received
    textstringMessage text
    avatarstringMessage user's avatar URL
    namestringMessage user's name
    imagestringMessage image URL
    headerstringMessage header
    footerstringMessage footer
    textHeaderstringMessage text header
    textFooterstringMessage text footer
    firstbooleanfalseDefines that the message is first in the conversation
    lastbooleanfalseDefines that the message is last in the conversation
    tailbooleanfalseDefines that the message has visual "tail". Usually last message in conversation
    sameNamebooleanfalseDefines that this message sender name is the same as on previous message
    sameHeaderbooleanfalseDefines that this message header text is the same as on previous message
    sameFooterbooleanfalseDefines that this message footer text is the same as on previous message
    sameAvatarbooleanfalseDefines that this message user's avatar URL is the same as on previous message

    メッセージイベント

    EventDescription
    <Message> events
    clickユーザーがメッセージのバブルをクリックするとイベントが発生する
    clickNameユーザーがメッセージのユーザー名をクリックするとイベントが発生する
    clickTextユーザがメッセージのテキストをクリックするとイベントが発生する
    clickAvatarユーザがメッセージユーザのアバターをクリックするとイベントが発生する
    clickHeaderユーザがメッセージのヘッダをクリックするとイベントが発生する
    clickFooterユーザーがメッセージのフッターをクリックするとイベントが発生する
    clickBubbleユーザがメッセージバブルをクリックするとイベントが発生します。

    メッセージスロット

    シングルメッセージのReactコンポーネント(<Message>)には、カスタム要素用のスロットが追加されています。

    • default - 要素は、最後に <div class="message-bubble"> 要素の子として挿入されます。
    • start - 要素は先頭に挿入され、メインのメッセージ要素 <div class="message"> の直接の子となります。
    • end - メインのメッセージ要素の直系の子として、最後に要素が挿入されます。
    • content-start - 要素は <div class="message-content"> 要素の先頭に挿入され、その直接の子となります。
    • content-end - <div class="message-content"> 要素の最後に挿入され、直接の子要素となります。
    • bubble-start -
      ` 要素の先頭に挿入され、直接の子要素となります。
    • bubble-end - <div class="message-bubble"> 要素の最後に挿入され、直接の子となります。default` スロットと同じです。

    以下のスロットは、1つのメッセージの中で、同じプロップの代わりに、より完全なレイアウトを渡す必要がある場合に使用できます。

    • header - 要素はメッセージのヘッダーに挿入されます。
    • footer - メッセージのフッターに挿入される要素です。
    • text - メッセージのテキストに挿入される要素です。
    • name - メッセージの名前に挿入される要素です。
    • image - メッセージのイメージに挿入される要素です(<img> 要素になります)。
    • text-header - メッセージのテキストヘッダーに挿入される要素です。
    • text-footer - メッセージのテキストフッターに挿入される要素です。
    <Message
      type="sent"
      text="Hello World"
      name="John Doe"
      avatar="path/to/image.jpg"
    >
      <div slot="start">Start</div>
      <div slot="end">End</div>
      <div slot="content-start">Content Start</div>
      <div slot="content-end">Content End</div>
      <div slot="bubble-start">Bubble Start</div>
      <div slot="bubble-end">Bubble End</div>
    </Message>
    
    {/* Renders to: */}
    
    <div class="message message-sent">
      <div>Start</div>
      <div class="message-avatar" style="background-image: url(path/to/image.jpg);"></div>
      <div class="message-content">
        <div>Content Start</div>
        <div class="message-name">John Doe</div>
        <div class="message-bubble">
          <div>Bubble Start</div>
          <div class="message-text">Hello World</div>
          <div>Bubble End</div>
        </div>
        <div>Content End</div>
      </div>
      <div>End</div>
    </div>
    

    Examples

    ここでは、Messagebarと一緒に使用できるメッセージページの完全な例を紹介します。

    import React, { useState, useEffect, useRef } from 'react';
    import {
      Page,
      Navbar,
      Messagebar,
      Link,
      MessagebarAttachments,
      MessagebarAttachment,
      MessagebarSheet,
      MessagebarSheetImage,
      Messages,
      MessagesTitle,
      Message,
      f7,
      f7ready,
    } from 'framework7-react';
    
    export default () => {
      const images = [
        'https://cdn.framework7.io/placeholder/cats-300x300-1.jpg',
        'https://cdn.framework7.io/placeholder/cats-200x300-2.jpg',
        'https://cdn.framework7.io/placeholder/cats-400x300-3.jpg',
        'https://cdn.framework7.io/placeholder/cats-300x150-4.jpg',
        'https://cdn.framework7.io/placeholder/cats-150x300-5.jpg',
        'https://cdn.framework7.io/placeholder/cats-300x300-6.jpg',
        'https://cdn.framework7.io/placeholder/cats-300x300-7.jpg',
        'https://cdn.framework7.io/placeholder/cats-200x300-8.jpg',
        'https://cdn.framework7.io/placeholder/cats-400x300-9.jpg',
        'https://cdn.framework7.io/placeholder/cats-300x150-10.jpg',
      ];
      const people = [
        {
          name: 'Kate Johnson',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
        },
        {
          name: 'Blue Ninja',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
        },
      ];
      const answers = [
        'Yes!',
        'No',
        'Hm...',
        'I am not sure',
        'And what about you?',
        'May be ;)',
        'Lorem ipsum dolor sit amet, consectetur',
        'What?',
        'Are you sure?',
        'Of course',
        'Need to think about it',
        'Amazing!!!',
      ];
      const [attachments, setAttachments] = useState([]);
      const [sheetVisible, setSheetVisible] = useState(false);
      const [typingMessage, setTypingMessage] = useState(null);
      const [messageText, setMessageText] = useState('');
      const [messagesData, setMessagesData] = useState([
        {
          type: 'sent',
          text: 'Hi, Kate',
        },
        {
          type: 'sent',
          text: 'How are you?',
        },
        {
          name: 'Kate',
          type: 'received',
          text: 'Hi, I am good!',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
        },
        {
          name: 'Blue Ninja',
          type: 'received',
          text: 'Hi there, I am also fine, thanks! And how are you?',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
        },
        {
          type: 'sent',
          text: 'Hey, Blue Ninja! Glad to see you ;)',
        },
        {
          type: 'sent',
          text: 'Hey, look, cutest kitten ever!',
        },
        {
          type: 'sent',
          image: 'https://cdn.framework7.io/placeholder/cats-200x260-4.jpg',
        },
        {
          name: 'Kate',
          type: 'received',
          text: 'Nice!',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
        },
        {
          name: 'Kate',
          type: 'received',
          text: 'Like it very much!',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
        },
        {
          name: 'Blue Ninja',
          type: 'received',
          text: 'Awesome!',
          avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
        },
      ]);
    
      const responseInProgress = useRef(false);
      const messagebar = useRef(null);
    
      const attachmentsVisible = () => {
        return attachments.length > 0;
      };
      const placeholder = () => {
        return attachments.length > 0 ? 'Add comment or Send' : 'Message';
      };
      useEffect(() => {
        f7ready(() => {
          messagebar.current = f7.messagebar.get('.messagebar');
        });
      });
      const isFirstMessage = (message, index) => {
        const previousMessage = messagesData[index - 1];
        if (message.isTitle) return false;
        if (
          !previousMessage ||
          previousMessage.type !== message.type ||
          previousMessage.name !== message.name
        )
          return true;
        return false;
      };
      const isLastMessage = (message, index) => {
        const nextMessage = messagesData[index + 1];
        if (message.isTitle) return false;
        if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name)
          return true;
        return false;
      };
      const isTailMessage = (message, index) => {
        const nextMessage = messagesData[index + 1];
        if (message.isTitle) return false;
        if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name)
          return true;
        return false;
      };
      const deleteAttachment = (image) => {
        const index = attachments.indexOf(image);
        attachments.splice(index, 1);
        setAttachments([...attachments]);
      };
      const handleAttachment = (e) => {
        const index = f7.$(e.target).parents('label.checkbox').index();
        const image = images[index];
        if (e.target.checked) {
          // Add to attachments
          attachments.unshift(image);
        } else {
          // Remove from attachments
          attachments.splice(attachments.indexOf(image), 1);
        }
        setAttachments([...attachments]);
      };
      const sendMessage = () => {
        const text = messageText.replace(/\n/g, '<br>').trim();
        const messagesToSend = [];
        attachments.forEach((attachment) => {
          messagesToSend.push({
            image: attachment,
          });
        });
        if (text.length) {
          messagesToSend.push({
            text,
          });
        }
        if (messagesToSend.length === 0) {
          return;
        }
        setAttachments([]);
        setSheetVisible(false);
        setMessagesData([...messagesData, ...messagesToSend]);
        setMessageText('');
    
        // Focus area
        if (text.length) messagebar.current.focus();
    
        // Mock response
        if (responseInProgress.current) return;
    
        responseInProgress.current = true;
    
        setTimeout(() => {
          const answer = answers[Math.floor(Math.random() * answers.length)];
          const person = people[Math.floor(Math.random() * people.length)];
          setTypingMessage({
            name: person.name,
            avatar: person.avatar,
          });
          setTimeout(() => {
            setTypingMessage(null);
            setMessagesData([
              ...messagesData,
              {
                text: answer,
                type: 'received',
                name: person.name,
                avatar: person.avatar,
              },
            ]);
            responseInProgress.current = false;
          }, 4000);
        }, 1000);
      };
    
      return (
        
          
        <Page>
          <Navbar title="Messages" backLink="Back"></Navbar>
    
          <Messagebar
            placeholder={placeholder()}
            attachmentsVisible={attachmentsVisible()}
            sheetVisible={sheetVisible}
            value={messageText}
            onInput={(e) => setMessageText(e.target.value)}
          >
            <Link
              iconIos="f7:camera_fill"
              iconAurora="f7:camera_fill"
              iconMd="material:camera_alt"
              slot="inner-start"
              onClick={() => {
                setSheetVisible(!sheetVisible);
              }}
            />
            <Link
              iconIos="f7:arrow_up_circle_fill"
              iconAurora="f7:arrow_up_circle_fill"
              iconMd="material:send"
              slot="inner-end"
              onClick={sendMessage}
            />
            <MessagebarAttachments>
              {attachments.map((image, index) => (
                <MessagebarAttachment
                  key={index}
                  image={image}
                  onAttachmentDelete={() => deleteAttachment(image)}
                />
              ))}
            </MessagebarAttachments>
            <MessagebarSheet>
              {images.map((image, index) => (
                <MessagebarSheetImage
                  key={index}
                  image={image}
                  checked={attachments.indexOf(image) >= 0}
                  onChange={handleAttachment}
                />
              ))}
            </MessagebarSheet>
          </Messagebar>
    
          <Messages>
            <MessagesTitle>
              <b>Sunday, Feb 9,</b> 12:58
            </MessagesTitle>
    
            {messagesData.map((message, index) => (
              <Message
                key={index}
                type={message.type}
                image={message.image}
                name={message.name}
                avatar={message.avatar}
                first={isFirstMessage(message, index)}
                last={isLastMessage(message, index)}
                tail={isTailMessage(message, index)}
              >
                {message.text && (
                  <span slot="text" dangerouslySetInnerHTML={{ __html: message.text }} />
                )}
              </Message>
            ))}
            {typingMessage && (
              <Message
                type="received"
                typing={true}
                first={true}
                last={true}
                tail={true}
                header={`${typingMessage.name} is typing`}
                avatar={typingMessage.avatar}
              />
            )}
          </Messages>
        </Page>
          
        
      );
    };