@sinchlabs/previewer

1.44.0 • Public • Published
Sinch Logo

Previewer

Previewing templates and messages compatible with Sinch Conversation API

Getting Started

  1. Create an .env file and paste the key to decrypt the package. Example below is just that and real keys needs to be provided by Sinch.

.env

DISTCRY = { "previewer": "p455w0rd" }
  1. Install the Previewer package
$ yarn add @sinchlabs/previewer

How To Use

You can use preview in several ways. By using one of the many implemented APIs or application components directly.

Using Previewer by specific API.

It allows to render the entire previewer by passing api-compatible message array. The example below shows a message from api which is passed to the conversation api previewer.

import { PreviewerConversationApi, ConversationChannel, ConversationDirection } from '@sinchlabs/previewer';

const messages = [
  {
    id: '',
    direction: ConversationDirection.UNDEFINED_DIRECTION,
    conversation_id: '',
    contact_id: '',
    metadata: '',
    accept_time: new Date(2020, 9, 17, 8, 59),
    app_message: {
      explicit_channel_message: {},
      text_message: {
        text: 'Hello :)',
      },
    },
  },
];

<PreviewerConversationApi
  channel={ConversationChannel.WHATSAPP}
  messages={messages}
/>;

Previewer also accepts the channel for which to render the message. The types are compatible with conversation api.

Using Previewer app components from modules/app directory.

Previewer allows to import any component from any application that is available. This is useful when you want to preview only a specific message, not the entire previewer. Components are written in typescript so we can easily see what parameters are passable.

import { TextWhatsApp } from '@sinchlabs/previewer/modules/apps/WhatsApp';

<TextWhatsApp
  text="Hello"
  incoming={true}
  date={new Date(2020, 9, 17, 8, 59)}
  RTLLayout={false}
/>;

In this example, we are importing a text message from the WhatsApp application that we want to display. The component allows parameters:

type Props = {
  text: string; // to render specific text
  mediaUrl?: string; // to display media (image/video). The text message allows you to display an image, and this is used, for example, to display the card message from the conversation api
  incoming?: boolean; // incoming / outgoing message
  date?: string | Date; // date
  RTLLayout?: boolean; // ability to display in right to left mode
};

All these parameters can be easily changed in the storybook under the apps/whatsapp/text tab.

Using Previewer with channels restrictions.

Previewer can handle restrictions in two ways (or together).

  • One is just informing that given channel has an error by error indicator in the channel dropdown. To make it work, StandardPhoneFrame component which contains channel dropdown must be wrapped with the RestrictionsProvider
  • Second is RestrictionsCard component which contain information about all channel messages limitations and found errors. To make it work, RestrictionsCard component must be wrapped with the RestrictionsProvider

RestrictionsProvider takes four props:

  • messages [type: ConversationMessage] (required): array of messages
  • onRestrictionError [type: (errors: RestrictionsChannelMessagesStatusType): void] (optional)
  • channelsWithErrorsDetails [type: channels: ConversationChannel[]] (optional): array of channels for which we will display the errors in RestrictionsCard (all by default)
  • enabledChannels [type: channels: ChannelIds] (optional): array of channels for which we should check errors.
import { useEffect, useState } from 'react';

import {
  ConversationChannel,
  RestrictionsProvider,
  RestrictionsCard,
  StandardPhoneFrame,
  PreviewerConversationApi,
} from '@sinchlabs/previewer';

export const ComponentWithRestrictions = (args) => {
  const [channel, setChannel] = useState(args.channel);

  useEffect(() => {
    setChannel(args.channel);
  }, [args.channel]);

  const onChannelSwitched = (newChannel: ConversationChannel) =>
    setChannel(newChannel);

  /* Optional - just in case if somebody would like to handle errors in the custom way  */
  const onRestrictionError = (
    _errors: RestrictionsChannelMessagesStatusType
  ) => {
    /* ... */
  };

  return (
    <RestrictionsProvider
      messages={messages}
      channelsWithErrorsDetails={[channel]}
    >
      {/*
       * `StandardPhoneFrame` wrapped with `RestrictionsProvider` provider will
       * automatically detect errors and show indicators
       */}
      <StandardPhoneFrame
        channel={channel}
        channelSwitcher={args.channelSwitcher}
        onChannelSwitched={onChannelSwitched}
      >
        <PreviewerConversationApi channel={channel} messages={messages} />
      </StandardPhoneFrame>
      {/* `RestrictionsCard` component can be placed anywhere inside `RestrictionsProvider`*/}
      <RestrictionsCard />
    </RestrictionsProvider>
  );
};

WhatsApp Template previewer

PreviewerWhatsAppBusinessAPI component takes four props:

  • messages [type: WhatsAppBusinessAPITemplate] (required): array of messages
  • RTLLayout [type: boolean] (optional): text direction
  • locale [type: boolean] (optional): language code used to format datetime
  • hour12 [type: boolean] (optional): hours format
import { useEffect, useState } from 'react';

import {
  StandardPhoneFrame,
  AppFrameWhatsApp,
  PreviewerWhatsAppBusinessAPI,
} from '@sinchlabs/previewer';

export const WhatsappPreviewer = () => {
  const [messages, setMessages] = useState<WhatsAppBusinessAPITemplate[]>([]);

  return (
    <StandardPhoneFrame>
      <AppFrameWhatsApp>
        <PreviewerWhatsAppBusinessAPI messages={messages} />
      </AppFrameWhatsApp>
    </StandardPhoneFrame>
  );
}; 

KakatoTalk Template previewer

PreviewerKakaoTalkTemplates component takes four props:

  • messages [type: KakaoTalkTemplate] (required): array of messages
  • RTLLayout [type: boolean] (optional): text direction
  • checkErrors [type: boolean] (optional): by default template previewer check for messages errors. If any error is detected, Error board with information is displayed.
  • onError [errors: KakaoTalkTemplateErrors] (optional): callback that returns an errors object
import { useEffect, useState } from 'react';

import {
  StandardPhoneFrame,
  AppFrameKakaoTalk,
  PreviewerKakaoTalkTemplates,
} from '@sinchlabs/previewer';

export const KakaoTalkPreviewer = () => {
  const [messages, setMessages] = useState<KakaoTalkTemplate[]>([]);

  /* Optional - just in case if somebody would like to handle errors in the custom way  */
  const handleError = (_errors: KakaoTalkTemplateErrors) => {
    /* ... */
  };

  return (
    <StandardPhoneFrame>
      <AppFrameKakaoTalk>
        <PreviewerKakaoTalkTemplates
          messages={messages}
          onError={handleError}
        />
      </AppFrameKakaoTalk>
    </StandardPhoneFrame>
  );
}; 

Project Structure

The general form of the project is as shown below:

    +-- assets
    +-- components
    +-- context
    |   +-- ChannelContext.ts
    |   +-- MessageContext.ts
    +-- hooks
    +-- icons
    +-- modules
    |   +-- apis
    |       +-- ConversationApi
    |       +-- RCSApi
    |       +-- SMSApi
    |       +-- WhatsAppApi
    |   +-- apps
    |       +-- AndroidMessages
    |       +-- Messenger
    |       +-- Viber
    |       +-- WhatsApp
    |   +-- deviceFrames
    |       +-- StandardPhoneFrame
    |       +-- TopBar
    +-- style
    |   +-- fonts.ts
    +-- types
    |   +-- client
    |   +-- RCS
    |   +-- SMS
    |   +-- WhatsApp
    +-- utils

The most important directory in the project is modules. There are components responsible for API processing and rendering of application components.

An example of what components the apis/ConversationAPI consists of:

    +-- apis/ConversationApi
    |   +-- AppFrameConversationApi
    |   +-- consts
    |       +-- FieldLimitationsConvesationApi.tsx
    |   +-- messages
    |     +-- CardConversationApi
    |     +-- CarouselConversationApi
    |     +-- ChoiceConversationApi
    |     +-- LocationConversationApi
    |     +-- MediaConversationApi
    |     +-- TextConversationApi
    |   +-- types
    |     +-- events.ts
    |   +-- AppMessage.tsx
    |   +-- ChannelSwitcher.tsx
    |   +-- index.ts
    |   +-- PreviewerConversationApi.tsx

In this case, the root component is PreviewerConversationApi.tsx. This is what you need to use the entire previewer responsible for processing the Conversation API. Among other things, it accepts props with an array of messages compatible with the api schema. Then it maps the message by going to the correct component for example CardConversationApi and depending on the channel uses the components found in apps. For example, for Viber it will choose components responsible for rendering this message.

An example of what components the apps/Viber consists of:

    +-- apps/Viber
    |   +-- AppFrameViber
    |   +-- components
    |   +-- consts
    |   +-- hooks
    |     +-- ButtonMessageViber
    |   +-- messages
    |     +-- ButtonMessageViber
    |     +-- CardBMViber
    |     +-- CardViber
    |     +-- CarouselViber
    |     +-- ChoiceViber
    |     +-- FileViber
    |     +-- ImageViber
    |     +-- LocationViber
    |     +-- TextViber
    |     +-- VideoViber
    |   +-- types
    |   +-- index.ts
    |   +-- MessageViber.tsx
    |   +-- styled.ts

Readme

Keywords

none

Package Sidebar

Install

npm i @sinchlabs/previewer

Weekly Downloads

2

Version

1.44.0

License

ISC

Unpacked Size

12.9 MB

Total Files

2512

Last publish

Collaborators

  • joaysi
  • szymonryczeksinch
  • viktorklangsinch