UNPKG

ringcentral-widgets

Version:
243 lines (228 loc) 7.6 kB
import { track, state, action, RcUIModuleV2, } from '@ringcentral-integration/core'; import { Module } from 'ringcentral-integration/lib/di'; import background from 'ringcentral-integration/lib/background'; import proxify from 'ringcentral-integration/lib/proxy/proxify'; import { isE164, parseIncompletePhoneNumber, } from '@ringcentral-integration/phone-number'; import { phoneTypes } from 'ringcentral-integration/enums/phoneTypes'; import { formatNumber } from 'ringcentral-integration/lib/formatNumber'; import { ContactModel } from 'ringcentral-integration/interfaces/Contact.model'; import { ContactDetailsViewProps, ContactDetailsViewFunctionProps, } from '../../components/ContactDetailsView/ContactDetailsView.interface'; import { Deps, RouteParams, InitParams, GetUIFunctions, } from './ContactDetailsUI.interface'; import { trackEvents } from './trackEvents'; import { contactReadyStates, ContactReadyState } from './contactReadyStates'; const DEFAULT_DIALER_ROUTE = '/dialer'; const DEFAULT_COMPOSE_TEXT_ROUTE = '/composeText'; @Module({ name: 'ContactDetailsUI', deps: [ 'Locale', 'RouterInteraction', 'ContactSearch', 'Contacts', 'ExtensionInfo', 'ExtensionFeatures', 'RateLimiter', 'RegionSettings', 'ConnectivityManager', 'Call', 'DialerUI', 'ComposeText', { dep: 'ContactDetailsUIOptions', optional: true, }, ], }) export class ContactDetailsUI extends RcUIModuleV2<Deps> { constructor(deps: Deps) { super({ deps }); } @state currentContact: ContactModel = null; @state currentContactReadyState: ContactReadyState = contactReadyStates.pending; @action private _setCurrentContact( readyState: ContactReadyState, contact: ContactModel, ) { this.currentContactReadyState = readyState; this.currentContact = contact; } @background async resetCurrentContact() { this._setCurrentContact(contactReadyStates.pending, null); } @background async initCurrentContact({ contactType, contactId }: InitParams) { if (this.currentContactReadyState !== contactReadyStates.pending) { return; } this._setCurrentContact(contactReadyStates.loading, null); const contact = await this._deps.contacts.findContact({ sourceName: contactType, contactId, }); // ignore result when it is reset during loading if (this.currentContactReadyState !== contactReadyStates.loading) { return; } this._setCurrentContact(contactReadyStates.loaded, contact as ContactModel); if (contact) { this._deps.contacts.getProfileImage(contact, false); this._deps.contacts.getPresence(contact, false); } } @proxify async showContactDetails({ id, type, direct = false }: RouteParams) { this._deps.routerInteraction.push( `/contacts/${type}/${id}${direct ? '?direct=true' : ''}`, ); } @proxify async handleClickToDial(contact: ContactModel, phoneNumber: string) { const recipient = { ...contact, phoneNumber, }; if (this._deps.call.isIdle) { this._deps.routerInteraction.push( this._deps.contactDetailsUIOptions?.dialerRoute ?? DEFAULT_DIALER_ROUTE, ); this._deps.dialerUI.call({ recipient }); } this._trackClickToCall(); } @proxify async handleClickToSMS(contact: ContactModel, phoneNumber: string) { const recipient = { ...contact, phoneNumber, }; this._deps.routerInteraction.push( this._deps.contactDetailsUIOptions?.composeTextRoute ?? DEFAULT_COMPOSE_TEXT_ROUTE, ); this._deps.composeText.addToNumber(recipient); if (this._deps.composeText.typingToNumber === recipient.phoneNumber) { this._deps.composeText.cleanTypingToNumber(); } this._trackClickToSMS(); } @track(trackEvents.clickToCall) private _trackClickToCall() {} @track(trackEvents.clickToSMS) private _trackClickToSMS() {} getUIProps(): ContactDetailsViewProps { return { currentLocale: this._deps.locale.currentLocale, contact: this.currentContact, isMultipleSiteEnabled: this._deps.extensionInfo.isMultipleSiteEnabled ?? false, isCallButtonDisabled: !!( this._deps.connectivityManager?.isOfflineMode || this._deps.connectivityManager?.isWebphoneUnavailableMode || this._deps.connectivityManager?.isWebphoneInitializing || this._deps.rateLimiter?.throttling ), disableLinks: !!( this._deps.connectivityManager?.isOfflineMode || this._deps.connectivityManager?.isVoipOnlyMode || this._deps.rateLimiter?.throttling ), showSpinner: !( this.currentContactReadyState === contactReadyStates.loaded && this._deps.locale.ready && this._deps.contactSearch.ready && this._deps.extensionFeatures.ready ), }; } getUIFunctions({ params }: GetUIFunctions): ContactDetailsViewFunctionProps { return { onVisitPage: () => { this.initCurrentContact(params); }, onLeavingPage: () => { this.resetCurrentContact(); }, formatNumber: (phoneNumber: string = '') => { if (!phoneNumber) { return phoneNumber; } // if the cleaned phone number is not a E164 format // we will show it directly, doesn't format it. const cleanedNumber: string = parseIncompletePhoneNumber( phoneNumber.toString(), ); const isE164Number = isE164(cleanedNumber); if (isE164Number) { const formattedNumber: string = formatNumber({ phoneNumber, countryCode: this._deps.regionSettings.countryCode, }); return formattedNumber; } // if multi-site is enabled then we will try to remove site code with same site if ( this._deps.extensionInfo.isMultipleSiteEnabled && this._deps.extensionInfo.site?.code ) { const formattedNumber: string = formatNumber({ phoneNumber, countryCode: this._deps.regionSettings.countryCode, siteCode: this._deps.extensionInfo.site?.code, isMultipleSiteEnabled: this._deps.extensionInfo .isMultipleSiteEnabled, }); return formattedNumber; } return phoneNumber; }, canTextButtonShow: (phoneType: string) => { const outboundSmsPermission = this._deps.extensionFeatures .hasOutboundSMSPermission; const internalSmsPermission = this._deps.extensionFeatures .hasInternalSMSPermission; // guess this statement is to avoid exception const isClickToTextEnabled = !!this._deps.composeText; return ( isClickToTextEnabled && phoneType !== phoneTypes.fax && (phoneType === phoneTypes.extension ? internalSmsPermission : outboundSmsPermission) ); }, canCallButtonShow: (phoneType: string) => { const isClickToDialEnabled = !!( this._deps.dialerUI && this._deps.extensionFeatures.isCallingEnabled ); return isClickToDialEnabled && phoneType !== phoneTypes.fax; }, onBackClick: () => { this._deps.routerInteraction.goBack(); }, onClickToDial: (contact: ContactModel, phoneNumber: string) => this.handleClickToDial(contact, phoneNumber), onClickToSMS: (contact: ContactModel, phoneNumber: string) => this.handleClickToSMS(contact, phoneNumber), }; } }