https://a.storyblok.com/f/270183/48152/a29f5b26b4/bootstrap_messaging.png

Crie uma interface de usuário simples para mensagens com o Bootstrap

Publicado em November 4, 2020

Tempo de leitura: 28 minutos

Bootstrap, originalmente chamado de Twitter Blueprint, foi desenvolvido por @mdo (Mark Otto) e @fat (Jacob Thornton) enquanto trabalhavam no Twitter, como uma forma de promover a consistência entre as ferramentas. Hoje, é uma das estruturas de front-end e um dos projetos de código aberto mais populares do mundo. Embora ainda seja considerado um atalho por muitos desenvolvedores de front-end, ele desempenhou um papel importante ao proporcionar uma experiência de usuário consistente e amigável a todos os desenvolvedores, em todo o mundo.

A internet está repleta de todos os tipos de exemplos de interfaces de usuário para mensagens, mas os desenvolvedores não têm muitas opções de frameworks que ofereçam interfaces desse tipo que sejam rápidas e fáceis de implementar, baseadas em algo tão simples quanto Bootstrape que não exijam muito CSS ou JavaScript personalizados. Você pode encontrar interfaces de usuário para mensagens para o Bootstrap por aí, mas nenhuma delas parece facilitar a vida ao usar componentes simples e padrão do biblioteca .

Neste guia, você vai aprimorar um aplicativo de bate-papo já existente com Bootstrap 4, utilizando componentes padrão e edições mínimas no CSS.

O aplicativo de demonstração e um exemplo finalizado já estão disponíveis no GitHub.

Pré-requisitos

Node e NPM

Para começar, você precisará ter o Node e o NPM instalados. Este guia utiliza o Node 8 e o NPM 6. Verifique se eles estão instalados e atualizados.

node --version npm --version

Tanto o Node quanto o NPM precisam estar instalados e na versão correta. Acesse o site nodejs.org e instale a versão correta, caso ainda não a tenha.

CLI da Vonage

Para configurar seu aplicativo, você precisará instalar o Vonage CLI. Instale-o usando o NPM no terminal.

npm install @vonage/cli -g

Crie um account gratuito na Vonage e configure o CLI da Vonage com a chave de API e o segredo encontrados no painel de controle.

vonage config:set --apiKey=VONAGE_API_KEY --apiSecret=VONAGE_API_SECRET

O CLI da Vonage possui plug-ins que, quando instalados, oferecem recursos adicionais. Neste tutorial, você trabalhará com o Conversations; portanto, eis o comando para instalar o plug-in correspondente:

vonage plugins:install @vonage/cli-plugin-conversations

Git (opcional)

Você pode usar o git para clonar o aplicativo de demonstração do GitHub.

Para quem não se sente à vontade com os comandos do Git, não se preocupe, eu te ajudo. Este guia traz instruções sobre como baixar o projeto como um arquivo ZIP.

Siga este guia para instalar o git.

O aplicativo de demonstração

O aplicativo de demonstração é simplesmente uma implementação básica do Client SDK do Conversation Client da Vonage , que é uma biblioteca JavaScript para implementar o WebRTC de forma rápida e fácil.

Instalação básica

Para facilitar o acompanhamento deste guia, clone o aplicativo de demonstração diretamente do GitHub.

git clone https://github.com/nexmo-community/bootstrap-styled-nexmo-chat.git

Para quem não se sente à vontade com os comandos do Git, é possível baixar o aplicativo de demonstração como um arquivo zip e descompactá-lo localmente.

Depois de clonada ou descompactada, acesse o novo diretório do aplicativo de demonstração.

cd bootstrap-styled-nexmo-chat

Instale as dependências do npm.

npm install

Configure a porta do aplicativo usando um arquivo de ambiente. Copie o arquivo de exemplo:

cp .env.example .env

Agora, edite o arquivo de ambiente .env e defina a porta como 3000 (ou qualquer outra porta que você precisar).

# app config PORT=3000

Entre os outros pacotes instalados pelo seu último comando, há um chamado nodemon, que permite que você recarregue seu aplicativo automaticamente caso edite algum arquivo.

Para iniciar o aplicativo da maneira padrão, execute:

npm start

Para iniciar o aplicativo, mas usando o nodemon, execute:

npm run dev

Dica: Se você estiver executando o aplicativo com nodemon pelo restante deste tutorial, sempre que eu sugerir reiniciar o aplicativo, você não precisará fazer isso, pois nodemon o sistema já faz isso por você. No entanto, se precisar se autenticar novamente no aplicativo, ainda será necessário fazer isso, já que as informações da sessão são armazenadas na memória e não estão configuradas para usar nenhum outro tipo de armazenamento.

Seja qual for a forma que você escolher para executar o aplicativo, assim que ele estiver em execução, você poderá testá-lo no seu navegador favorito, que deverá conseguir localizá-lo rodando localmente: http://localhost:3000.

A blank, broken Chat applicationA blank, broken Chat application

A tela está praticamente em branco, não dá para enviar mensagens para ninguém e, se você verificar o console do navegador, encontrará erros da API da Vonage, pois é hora de configurar o aplicativo.

Configurar o aplicativo de demonstração

Para se conectar ao Vonage e enviar ou receber mensagens pelo serviço, é necessário configurar o aplicativo de demonstração.

Criar uma aplicação da Vonage

Primeiro, crie uma Application da Vonage com recursos de RTC (comunicação em tempo real). A URL do evento será um registro em tempo real dos eventos que ocorrem no serviço da Vonage, como usuários entrando ou saindo, enviando mensagens e ativando o áudio (caso você queira ativá-lo).

vonage apps:create "Vonage RTC Chat" --rtc_event_url=http://example.com

Criar uma conversa no Vonage

Em segundo lugar, crie uma “Conversação” do Vonage, que funciona como uma sala de bate-papo. Ou seja, um espaço para mensagens e eventos.

vonage apps:conversations:create "Bootstrap Chat"

Crie sua conta

Agora, crie uma conta para você mesmo.

Observação: Nesta demonstração, não haverá bate-papo entre dois usuários. Outros guias mostram como criar conversas entre vários usuários. Este guia se concentra em definir o estilo da interface de usuário das mensagens de maneira simples, mas atraente.

vonage apps:users:create USER_NAME --display_name=DISPLAY_NAME

Adicionar o usuário a uma conversa

Em seguida, adicione seu novo usuário à conversa. Um usuário pode ser membro de uma Application, mas ainda assim precisa participar da conversa.

vonage apps:conversations:members:add CONVERSATION_ID USER_ID

Gerar um token de usuário

Por fim, gere um token para o seu novo usuário. Esse token representa o usuário ao acessar o aplicativo. Esse token de acesso identifica o usuário; portanto, qualquer pessoa que o utilizar será considerada o usuário correto.

Na prática, você configurará o aplicativo com esse token. Em ambiente de produção, esses tokens devem ser protegidos, mantidos em sigilo e divulgados com muito cuidado ao aplicativo cliente, se for o caso.

vonage jwt --key_file=./vonage_rtc_chat.key --acl='{"paths":{"/*/users/**":{},"/*/conversations/**":{},"/*/sessions/**":{},"/*/devices/**":{},"/*/image/**":{},"/*/media/**":{},"/*/push/**":{},"/*/knocking/**":{},"/*/legs/**":{}}}' --subject=USER_NAME --app_id=APP_ID

Configurar o aplicativo

Depois de gerar todas as partes necessárias, edite o views/layout.hbs arquivo e localize o código JavaScript mostrado aqui:

<script>
      var userName = '';
      var displayName = '';
      var conversationId = '';
      var clientToken = '';
    </script>

Edite o arquivo de configuração com os valores que você gerou nos comandos acima.

<script>
      var userName = 'luke'; // <USER_NAME>
      var displayName = 'Luke Oliff'; // <DISPLAY_NAME>
      var conversationId = 'CON-123...y6346'; // <CONVERSATION_ID>
      var clientToken = 'eyJhbG9.eyJzdWIiO.Sfl5c'; // this will be much much longer
    </script>

Agora que a configuração está pronta, reinicie o aplicativo. Acesse-o usando a mesmo URL do aplicativo.

A primeira coisa que você vai notar é uma mensagem informando que você entrou na conversa com esse usuário.

An almost blank, working Chat applicationAn almost blank, working Chat application

Então, você poderá enviar algumas mensagens usando o formulário, onde poderá enviar mensagens para si mesmo à vontade.

Sending some messages to our working Chat applicationSending some messages to our working Chat application

Interface de usuário simples para mensagens com Bootstrap

Com seu aplicativo básico já em funcionamento, agora você pode personalizá-lo usando o Bootstrap.

Cada etapa deste guia é enviada individualmente para o ramo de exemplo finalizado deste projeto. Portanto, se a qualquer momento você encontrar um erro no processo, poderá consultar os próprios commits. Você também encontrará links para o commit relevante em cada etapa.

O HTML

Incorporando o Bootstrap ao aplicativo

Você começará editando o views/layout.hbs arquivo still e modificando o design principal do aplicativo para incluir os recursos CSS e JavaScript do Bootstrap.

Após o guia de introdução ao Bootstrap , adicione esta <link> tag dentro do seu <head> antes de todas as outras folhas de estilo, para carregar os recursos CSS. A <link> tag abaixo é um exemplo; você pode consultar o commit no aplicativo de demonstração ou usar a <link> no guia de introdução do Bootstrap.

<!-- views/layout.hbs -->
<!DOCTYPE html>
<html>
  <head>
    <!-- //... -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/..." integrity="..." crossorigin="anonymous">
    <!-- //... -->
  </head>

  <!-- //... -->

Além disso, você precisará das bibliotecas recomendadas do Bootstrap e do JavaScript. Essas, sem dúvida, não são obrigatórias neste caso. No entanto, muitos dos componentes do Bootstrap exigem o uso de JavaScript para funcionar corretamente, dependendo também do Popper.js e do jQuery. Mais uma vez, você pode consultar o commit no aplicativo de demonstração ou usar as <script> tags no guia de Introdução ao Bootstrap.

<!-- views/layout.hbs -->

<!-- //... -->

  <!-- //... -->
  
    <!-- //... -->
    <script src="https://code.jquery.com/..." integrity="..." crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js..." integrity="..." crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/..." integrity="..." crossorigin="anonymous"></script>
  </body>
</html>

Reinicie o aplicativo e dê uma olhada novamente. Você pode ver que essas alterações tiveram um efeito mínimo.

Styled the working Chat application with BootstrapStyled the working Chat application with Bootstrap

Adicionando componentes de navegação e contêineres

Agora que o Bootstrap está incluído no seu aplicativo, você pode adicionar seu <nav> e ao contêiner no layout principal.

Ainda em edição views/layout.hbs, adicione o código a seguir para envolver a expressão existente {{{body}}} expressão existente.

<!-- views/layout.hbs -->

<!-- //... -->

  <!-- //... -->
    <nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
      <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">{{title}}</a>
    </nav>

    <div class="container-fluid">
      <div class="row">

        <main role="main" class="col-md-12">
          <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
            <h1 class="h2">Bootstrap Chat</h1>
          </div>

          {{{body}}}

        </main>
      </div>
    </div>
  <!-- //... -->

<!-- //... -->

Se você quiser ver as alterações exatas feitas no arquivo, pode dar uma olhada em o commit.

Agora você verá que adicionou uma barra de navegação, mas o chat continua sem estilo, o que causa alguns problemas de exibição. Reinicie o aplicativo para ver como ficou agora.

Added navbar and container to Chat applicationAdded navbar and container to Chat application

Listas e entradas

Como as interfaces de usuário de mensagens consistem em uma lista de mensagens, você usará um elemento de lista <ul> de forma semântica.

Editar views/index.hbs e altere o <div id="messageFeed"> para um elemento de lista não ordenada (com marcadores) <ul> conforme mostrado. A list-unstyled classe é uma classe do Bootstrap que remove os marcadores e o recuo do estilo nativo da lista.

<ul class="list-unstyled" id="messageFeed">
        </ul>

Usar a marcação semântica adequada para listas tem a vantagem de exibir as informações corretamente em navegadores de texto e leitores de tela. Suas mensagens acabarão sendo <li> também.

Ao editar views/index.hbs, você pode aproveitar para fazer as seguintes substituições. Localize esses dois <input> elementos.

          <input type="text" id="messageTextarea">
          <input type="button" id="send" value="Send" />

Substitua-os por esta marcação, que contém um grupo de botões do Bootstrap, uma área de texto com estilo e um botão “Enviar”.

<div class="input-group mb-3">
            <input type="text" class="form-control" id="messageTextarea">
            <div class="input-group-append">
              <button class="btn btn-outline-secondary" type="button" id="send">Send</button>
            </div>
          </div>

Dê uma olhada em o commit para ver exatamente como o arquivo deve ser editado.

Reinicie o aplicativo e dê uma olhada novamente. Embora você tenha alterado a forma como as mensagens são adicionadas, isso não mudou muito no estilo. Mas, pelo menos, o formulário está mais próximo do que se esperaria de uma interface de usuário de mensagens.

Chat application now using list items and chat-style inputsChat application now using list items and chat-style inputs

O CSS

Depois de concluir as alterações na marcação, algumas coisas estranhas estão acontecendo no layout.

Essas três alterações no CSS podem ser visualizadas em um único commit em public/stylesheets/style.css.

Margens fixas da barra de navegação

A primeira alteração no CSS consiste em adicionar padding-top ao contêiner de conteúdo principal, levando em conta a altura da barra de navegação (40px) e um espaço em branco adequado com base no estilo padrão do Bootstrap (8px).

/* ... */

[role="main"] {
  padding-top: 48px; /* space for fixed navbar (40px) and margin (8px) */
}

Reinicie o aplicativo e tente novamente.

Fixed header margins in chat applicationFixed header margins in chat application

Feed de mensagens com rolagem

Essa alteração messageFeed fixa a altura do elemento que contém nossas mensagens em 100% da altura da janela de visualização, menos as alturas da barra de navegação (48 px), da barra de título principal (71 px) e do rodapé (ainda a ser estilizado, com 53 px).

/* ... */

#messageFeed {
  height: calc(100vh - 172px); /* space for fixed navbar (48px), "main" title (71px), footer (53px) */
  overflow-y: scroll; /* vertical scroll for the message feed */
}

Reinicie o aplicativo e experimente. Para ver a rolagem de overflow para o messageFeed, você precisará enviar mais algumas mensagens.

Chat application message feed now scrollableChat application message feed now scrollable

Entrada de texto fixo para o envio de mensagens

Essa última alteração no CSS é para o <footer>, que contém o campo de texto e o botão. É recomendável fixá-los na parte inferior da janela, ocupando toda a largura. Defina a altura (53px), atribua uma cor de fundo e adicione uma margem lateral padrão definida pelo tema do Bootstrap.

/* ... */

#messages footer {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%; /* 100% of page width */
  padding: 0 15px 15px 15px; /* standard edge margin (15px) */
  height: 53px; /* space for input height (38px) + bottom padding (15px) */
  background-color: #fff;
}

Reinicie o aplicativo e tente novamente.

Chat application inputs now fixed to footerChat application inputs now fixed to footer

O JavaScript

As últimas alterações que você fará no aplicativo de demonstração dizem respeito ao código JavaScript que acompanha a demonstração. Todas essas alterações são feitas no public/javascripts/chat.js arquivo.

Marcação para o evento “Membro Admitido”

Edite o arquivo e localize a memberJoined função. Altere-a para que retorne um item de lista <li> , conforme mostrado abaixo.

// public/javascripts/chat.js

//...

  memberJoined(member, event) {
    const date = new Date(Date.parse(event.timestamp));

    return `<li class="my-2 text-center">` +
    `<p>${member.display_name} joined the conversation <small>@ ${date.toLocaleString('en-GB')}</small></p>` +
    `</li>`;
  }

//...

Para ver como a função JavaScript foi modificada, dê uma olhada em o commit.

Reinicie o aplicativo e tente novamente usando a URL do aplicativo. Agora você verá que a mensagem de que o usuário entrou no grupo está bem centralizada no feed de mensagens.

Chat application events now using line itemsChat application events now using line items

Marcação para mensagens “De mim” e “Para mim”

No mesmo arquivo, localize a senderMessage função. Edite-a para que retorne um item da lista <li> que seja um objeto de mídia. Os objetos Media são semelhantes às mensagens, pois possuem um título (para o autor e os metadados), conteúdo (a mensagem) e uma imagem opcional.

Nesse caso, você tem uma condição que determina o resultado:

  • Um objeto Media padrão, se o atual user.name for igual à mensagem user.name - De-Mim.

  • Um objeto Media com o texto alinhado à direita, se o atual user.name não for igual à mensagem user.name - Para mim.

// public/javascripts/chat.js

//...

  senderMessage(user, sender, message) {
    const date = new Date(Date.parse(message.timestamp))
    var output = '';

    if (user.name === sender.user.name) {
      output = `<li class="media my-3">` +
      `<div class="media-body">` +
      `<h5 class="mt-0 mb-1">${sender.display_name} <small>@ ${date.toLocaleString('en-GB')}</small></h5>` +
      message.body.text +
      `</div>` +
      `</li>`;
    } else {
      output = `<li class="media my-3">` +
      `<div class="media-body text-right">` +
      `<h5 class="mt-0 mb-1">${sender.display_name} <small>@ ${date.toLocaleString('en-GB')}</small></h5>` +
      message.body.text +
      `</div>` +
      `</li>`;
    }

    return output;
  }

//...

Para ver como essa função JavaScript foi modificada, dê uma olhada em o commit.

Reinicie o aplicativo e tente novamente usando a URL padrão: http://localhost:3000. Agora você verá que suas mensagens estão com uma formatação bem bonita.

Now using from-me and to-me message style in chat applicationNow using from-me and to-me message style in chat application

Adicionar avatares do Adorable.io para os usuários

Como não há perfis de usuário no seu aplicativo, a ausência de avatares faz com que ele pareça um pouco vazio. Portanto, para dar um acabamento ao objeto `Media` e conferir a ele o visual de um aplicativo de bate-papo moderno, você pode usar um serviço de avatares provisórios como adorable.io com base nas informações do usuário.

O `Adorable` aceita qualquer sequência de caracteres como parte de uma URL, https://api.adorable.io/avatars/64/my-string-here.png e retorna um rosto engraçado. É uma ótima maneira de adicionar uma imagem provisória que muda de acordo com o usuário.

Então, ainda editando o mesmo arquivo, volte à senderMessage função e adicione esta linha após o elemento de item de linha de abertura <li> , para mensagens de-mim.

// public/javascripts/chat.js

//...

      `<img src="https://api.adorable.io/avatars/64/${btoa(sender.display_name)}.png" class="mr-3" alt="" />` +

//...

Em seguida, adicione esta linha no arquivo parte “to-me” da condição, logo antes do elemento de fechamento do item de linha </li> .

// public/javascripts/chat.js

//...

      `<img src="https://api.adorable.io/avatars/64/${btoa(sender.display_name)}.png" class="ml-3" alt="" />` +

//...

A diferença fundamental entre essas linhas é que uma delas contém a mr-3 classe, e a outra tem a ml-3 classe. Uma é para uma imagem alinhada à esquerda com uma margem à direita. A outra, para uma imagem alinhada à direita com uma margem à esquerda. Confundir essas duas pode fazer com que o resultado pareça um pouco estranho. Então, dê uma olhada neste este commit para conferir se você entendeu tudo corretamente.

Quando estiver satisfeito com as alterações, reinicie e dê uma olhada no aplicativo.

Adorable.io avatars in chat applicationAdorable.io avatars in chat application

Adicionar a opção “Rolar até o final” para mensagens

As interfaces de usuário convencionais de mensagens exibem as mensagens mais recentes na parte inferior, e você precisa rolar a tela para cima para ver as mais antigas. O aplicativo de demonstração também organiza as mensagens e os eventos dessa forma. Portanto, para manter o foco no conteúdo correto, agora você pode adicionar o código a seguir. Esse código fará com que o feed de mensagens role automaticamente até o final quando uma nova mensagem chegar, mas somente se o feed já estiver na parte inferior. Dessa forma, digamos que você role para cima para ver mensagens mais antigas: nada acontecerá.

Adicione duas novas funções ao chat.js arquivo. A primeira função retornará um valor booleano, indicando se messageFeed está na parte inferior ou não. A outra fará a rolagem messageFeed até o final da página.

// public/javascripts/chat.js

//...

  isFeedAtBottom() {
    return (this.messageFeed.offsetHeight+this.messageFeed.scrollTop)===this.messageFeed.scrollHeight;
  }

  scrollFeedToBottom() {
    this.messageFeed.scrollTop = this.messageFeed.scrollHeight;
  }
  
//...

Em seguida, modifique os ouvintes de eventos para novas mensagens enviadas e novos participantes adicionados à conversa. Em ambos os casos, você registrará a posição de rolagem do feed de mensagens antes de adicionar o item. Depois, você fará a rolagem (ou não) com base no contexto anterior à alteração.

// public/javascripts/chat.js

//...

  setupConversationEvents(conversation, user) {
    //...

    conversation.on('text', (sender, message) => {
      var feedAtBottom = this.isFeedAtBottom();

      // ...

      if (feedAtBottom) {
        this.scrollFeedToBottom();
      }
    })

    conversation.on("member:joined", (member, event) => {
      var feedAtBottom = this.isFeedAtBottom();

      // ...

      if (feedAtBottom) {
        this.scrollFeedToBottom();
      }
    })
  
    //...

  }
  
//...

A última alteração no aplicativo de demonstração é fazer com que o feed de mensagens role até o final da página quando ela for carregada. Portanto, após a linha em que você adiciona o eventsHistory ao feed de mensagens (this.messageFeed.innerHTML = eventsHistory + this.messageFeed.innerHTML), adicione this.scrollFeedToBottom();.

// public/javascripts/chat.js

//...

  showConversationHistory(conversation, user) {
    // ...

      // ...

        this.messageFeed.innerHTML = eventsHistory + this.messageFeed.innerHTML;

        this.scrollFeedToBottom();

      // ...

    // ...
  }

//...

Para ter certeza de que você aplicou essa alteração corretamente, você pode visualizar o commit.

Quando estiver satisfeito com as alterações, reinicie e dê uma olhada no aplicativo.

Chat application message feed now scrolls to bottomChat application message feed now scrolls to bottom

Fim

Se eu estivesse criando um aplicativo de bate-papo, seria assim que eu gostaria que fosse.

Espero que este guia sobre como criar uma interface de usuário para mensagens seja útil para você. Ele inclui os conceitos básicos, como De mim e Para mim , rolagem automática até o final da página e espaços reservados para o avatar do usuário.

Agora você pode aplicar essas técnicas de interface do usuário em outros tutoriais do Vonage Client SDK, como Adicionar funcionalidade de Voice a um aplicativo de bate-papo existente, “Cadastre-se para conversar com o Typeform”e a Visão geral do Client SDK do JavaScript.

Alguns dos nossos outros guias abordam o envio de mensagens entre vários usuários! Desafio você a fazer com que vários usuários troquem mensagens entre si usando uma interface de mensagens com um visual bacana e a compartilhar seu progresso.

Chat application using multiple usersChat application using multiple users

E não se esqueça: se tiver alguma dúvida, sugestão ou ideia que gostaria de compartilhar com a comunidade em geral, sinta-se à vontade para participar do nosso espaço de trabalho da Comunidade no Slack ou deixar uma resposta aqui embaixo 👇.

Compartilhar:

https://a.storyblok.com/f/270183/250x250/451101b4f0/lukeoliff.png
Luke OliffEx-funcionários da Vonage

Educador de tecnologia com um jeito amigável, pai de família, defensor da diversidade, provavelmente discuto um pouco demais. Ex-engenheiro de backend. Fale comigo sobre JavaScript (front-end ou back-end), o incrível Vue.js, DevOps, DevSecOps e tudo relacionado ao JamStack. Escritor no DEV.to