ringcentral-widgets
Version:
RingCentral Integration Widget Library
243 lines (228 loc) • 7.6 kB
text/typescript
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';
export class ContactDetailsUI extends RcUIModuleV2<Deps> {
constructor(deps: Deps) {
super({ deps });
}
currentContact: ContactModel = null;
currentContactReadyState: ContactReadyState = contactReadyStates.pending;
private _setCurrentContact(
readyState: ContactReadyState,
contact: ContactModel,
) {
this.currentContactReadyState = readyState;
this.currentContact = contact;
}
async resetCurrentContact() {
this._setCurrentContact(contactReadyStates.pending, null);
}
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);
}
}
async showContactDetails({ id, type, direct = false }: RouteParams) {
this._deps.routerInteraction.push(
`/contacts/${type}/${id}${direct ? '?direct=true' : ''}`,
);
}
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();
}
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();
}
private _trackClickToCall() {}
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),
};
}
}