1.44.0 • Published 28 days ago

@sinchlabs/previewer v1.44.0

Weekly downloads
-
License
ISC
Repository
gitlab
Last release
28 days ago

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:

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:

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:

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 CardConversationApiand 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