@sinchlabs/previewer
v1.44.0
Published
<div align="center"> <img src="https://1vxc0v12qhrm1e72gq1mmxkf-wpengine.netdna-ssl.com/wp-content/uploads/2020/04/cropped-Sinch-PR-1000-300x141-1.png" width="320" alt="Sinch Logo" /> </div>
Downloads
22
Keywords
Readme
Getting Started
- 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" }
- 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 theRestrictionsProvider
- 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 theRestrictionsProvider
RestrictionsProvider
takes four props:
messages
[type:ConversationMessage
] (required): array of messagesonRestrictionError
[type:(errors: RestrictionsChannelMessagesStatusType): void
] (optional)channelsWithErrorsDetails
[type:channels: ConversationChannel[]
] (optional): array of channels for which we will display the errors inRestrictionsCard
(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 messagesRTLLayout
[type:boolean
] (optional): text directionlocale
[type:boolean
] (optional): language code used to format datetimehour12
[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 messagesRTLLayout
[type:boolean
] (optional): text directioncheckErrors
[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