Created
February 15, 2023 04:43
-
-
Save rationalthinker1/8e0b40053f94060fd055af2b21937918 to your computer and use it in GitHub Desktop.
MightyCall.ts Rewritten
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const MIGHTYCALL_API_URL = 'https://api.mightycall.com/v4/webphone'; | |
const MIGHTYCALL_CORE_URL = 'https://api.mightycall.com/v4/webphone/JavaScriptSDK/mightycall.webphone.core.js'; | |
// eslint-disable-next-line @typescript-eslint/no-explicit-any | |
declare let MightyCallWebPhoneCore: any; | |
const MIGHTYCALL_EVENT = 'mightycall_event'; | |
const MIGHTYCALL_WEBPHONE_STATUS = 'mightycall_webphone_status'; | |
enum CallStatus { | |
INACTIVE = 'inactive', | |
OFFLINE = 'offline', | |
READY = 'ready', | |
CALL_INCOMING = 'call_incoming', | |
CALL_OUTGOING = 'call_outgoing', | |
CALL_STARTED = 'call_started', | |
} | |
interface Config { | |
login?: string, | |
password?: string, | |
integrationType?: string, | |
} | |
let INTEGRATION_CONFIG: Config = {}; | |
let SDK_CONFIG = {}; | |
export class Utility { | |
public getWebPhoneWindowReference: () => Window; | |
protected platform: string; | |
constructor() { | |
this.getWebPhoneWindowReference = this.getWindowReference; | |
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | |
// @ts-ignore | |
this.platform = navigator?.vendor ?? navigator?.userAgentData?.platform ?? navigator?.platform ?? 'unknown'; | |
} | |
initWebPhoneWindow = () => { | |
this.getWindowReference(); | |
}; | |
initWebPhoneInline = (containerId: string) => { | |
this.getWebPhoneWindowReference = this.noopReturnWindow; | |
this.initWebPhoneFrame(containerId); | |
this.appendCoreJsToDocument(); | |
}; | |
getWindowReference = () => { | |
const reference = window.open('', 'mightycall_webphone_expand', 'width=345,height=500,location=false,status=false'); | |
if (this.platform.indexOf('Apple') == 0 && /\sSafari\//.test(navigator.userAgent)) { | |
window.resizeTo(360, 550); | |
} | |
if (navigator.userAgent.indexOf('Firefox') > -1) { | |
window.resizeTo(360, 565); | |
} | |
const location = this.getFrameSrc(); | |
console.log('wf location = ', location); | |
try { | |
if (this.isEmptyReference(reference)) { | |
reference.location = location; | |
} | |
} catch (e) { | |
console.log(e); | |
} | |
return reference; | |
}; | |
initWebPhoneFrame = (containerId: string) => { | |
const frame = document.createElement('iframe'); | |
frame.id = 'mightyCallWebPhoneFrame'; | |
frame.src = this.getFrameSrc(); | |
frame.allow = 'microphone; autoplay'; | |
console.log('wf location = ', frame.src); | |
let style = 'width:345px;height:500px;'; | |
frame.name = 'mightycall_webphone_expand'; | |
if (this.platform.indexOf('Apple') == 0 && /\sSafari\//.test(navigator.userAgent)) { | |
style = 'width:360px;height:550px;'; | |
} | |
if (navigator.userAgent.indexOf('Firefox') > -1) { | |
style = 'width:360px;height:565px;'; | |
} | |
frame.setAttribute('style', style); | |
document.getElementById(containerId).appendChild(frame); | |
}; | |
appendCoreJsToDocument = () => { | |
const script = document.createElement('script'); | |
script.src = MIGHTYCALL_CORE_URL; | |
script.type = 'text/javascript'; | |
document.head.appendChild(script); | |
}; | |
noopReturnWindow = () => { | |
return window; | |
}; | |
getLocation = () => { | |
return location.origin; | |
}; | |
getFrameSrc = () => { | |
const config = INTEGRATION_CONFIG; | |
if ((!config.login || !config.password) && !config.integrationType) { | |
throw 'Config is empty. May you forget to call applyConfig?'; | |
} | |
const uriParams = [ `integration=${encodeURIComponent(this.getLocation())}` ]; | |
if (config.login) { | |
uriParams.push( | |
`client_id=${encodeURIComponent(config.login)}`, | |
`client_secret=${encodeURIComponent(config.password)}`); | |
} | |
if (config.integrationType) { | |
uriParams.push(`integration_type=${encodeURIComponent(config.integrationType)}`); | |
} | |
return `${MIGHTYCALL_API_URL}/Oauth/StartBuiltInIntegration?${uriParams.join('&')}#enable`; | |
}; | |
guid = () => { | |
function s4() { | |
return Math.floor((1 + Math.random()) * 0x10000) | |
.toString(16) | |
.substring(1); | |
} | |
return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`; | |
}; | |
addEventHandler = (eventName: string, handler: (this: Window, ev: Event) => void) => { | |
if (window.addEventListener) { | |
window.addEventListener(eventName, handler); | |
} else if ('attachEvent' in window && typeof window.attachEvent === 'function') { | |
window.attachEvent('on' + eventName, handler); | |
} | |
}; | |
isEmptyReference = (ref: Window = null) => { | |
const reference = ref || window.open('', 'mightycall_webphone_expand', 'width=345,height=500,location=false,status=false'); | |
//iframe case | |
if (reference.self !== reference.top) { | |
//special check for yandex case | |
try { | |
if (reference.location.href) { | |
return true; | |
} | |
} catch (e) { | |
console.warn(e); | |
} | |
return false; | |
} | |
try { | |
if ( | |
reference.location.href && reference.location.host !== location.host | |
) { | |
return true; | |
} | |
} catch (e) { | |
console.warn(e); | |
} | |
return false; | |
}; | |
} | |
export class EventObserver { | |
protected handlers: Array<(...args) => unknown> = []; | |
subscribe = (fn: (...args) => unknown) => { | |
this.handlers.push(fn); | |
}; | |
unsubscribe = (fn: (...args) => unknown) => { | |
this.handlers = this.handlers.filter((item) => item !== fn); | |
}; | |
fire = (o: unknown, thisObj: Window & typeof globalThis) => { | |
const scope = thisObj || window; | |
this.handlers.forEach((item) => item.call(scope, o)); | |
}; | |
} | |
export class MightyCallProfile { | |
public OnStatusChange = new EventObserver(); | |
protected utility = new Utility(); | |
profileGetUserStatusPromise = () => { | |
this.utility.getWebPhoneWindowReference(); | |
return MightyCallWebPhoneCore.Profile.GetUserStatus(); | |
}; | |
profileSetUserStatusPromise = (statusStr: string) => { | |
this.utility.getWebPhoneWindowReference(); | |
return MightyCallWebPhoneCore.Profile.SetUserStatus(statusStr); | |
}; | |
} | |
export class MightyCallPhone { | |
public OnStatusChange = new EventObserver(); | |
public OnInactive = new EventObserver(); | |
public OnOffline = new EventObserver(); | |
public OnReady = new EventObserver(); | |
public OnCallIncoming = new EventObserver(); | |
public OnLoadConfig = new EventObserver(); | |
public CallPartiesChanged = new EventObserver(); | |
public OnCallOutgoing = new EventObserver(); | |
public OnCallStarted = new EventObserver(); | |
public OnCallCompleted = new EventObserver(); | |
public OnAccept = new EventObserver(); | |
public OnReject = new EventObserver(); | |
public OnHangUp = new EventObserver(); | |
public OnMute = new EventObserver(); | |
public OnUnMute = new EventObserver(); | |
public OnHold = new EventObserver(); | |
public OnUnHold = new EventObserver(); | |
public OnFail = new EventObserver(); | |
protected utility = new Utility(); | |
Init = (containerId: string) => { | |
if (containerId) { | |
this.utility.initWebPhoneInline(containerId); | |
} else { | |
this.utility.initWebPhoneWindow(); | |
} | |
this.overrideSetItem(); | |
this.appendCoreJsToDocument(); | |
}; | |
overrideSetItem = () => { | |
const originalSetItem = Storage.prototype.setItem; | |
const handleNotifications = this.handleNotifications; | |
Storage.prototype.setItem = function(key, data) { | |
handleNotifications({key: key, newValue: data}); | |
originalSetItem.apply(this, [ key, data ]); | |
}; | |
}; | |
appendCoreJsToDocument = () => { | |
const script = document.createElement('script'); | |
script.src = MIGHTYCALL_CORE_URL; | |
script.type = 'text/javascript'; | |
document.head.appendChild(script); | |
}; | |
handleNotifications = (event) => { | |
if (event.key == MIGHTYCALL_EVENT) { | |
const data = JSON.parse(event.newValue); | |
this.fireEvent(data); | |
} | |
}; | |
fireEvent = (data) => { | |
try { | |
if (this[data.type] != undefined && this[data.type][data.event] != undefined) { | |
this[data.type][data.event].fire(data.info); | |
} | |
} catch (exc) { | |
console.warn(`error firing ${data.type} ${data.event}`); | |
console.warn(exc); | |
} | |
}; | |
Focus = () => { | |
const webPhoneInstanceReference = this.utility.getWebPhoneWindowReference(); | |
webPhoneInstanceReference.focus(); | |
}; | |
Call = (number: string) => { | |
console.log(`call number: ${number}`); | |
const callUrgent = () => { | |
MightyCallWebPhoneCore.Phone.Call(number); | |
this.OnReady.unsubscribe(callUrgent); | |
}; | |
if (this.utility.isEmptyReference()) { | |
this.utility.getWebPhoneWindowReference(); | |
this.OnReady.subscribe(callUrgent); | |
} else { | |
callUrgent(); | |
} | |
}; | |
SetNumber = (number: string, isTurnOn = true) => { | |
MightyCallWebPhoneCore.Phone.SetNumber(number, isTurnOn); | |
}; | |
SwitchOff = () => { | |
MightyCallWebPhoneCore.Phone.SwitchOff(); | |
}; | |
SwitchOn = () => { | |
MightyCallWebPhoneCore.Phone.SwitchOn(); | |
}; | |
PhoneStatus = (): CallStatus => { | |
let status = localStorage.getItem(MIGHTYCALL_WEBPHONE_STATUS) as CallStatus; | |
if (status == undefined) { | |
status = CallStatus.INACTIVE; | |
} | |
return status; | |
}; | |
PhoneAccept = () => { | |
MightyCallWebPhoneCore.Phone.Accept(); | |
}; | |
PhoneReject = () => { | |
MightyCallWebPhoneCore.Phone.Reject(); | |
}; | |
PhoneHangUp = () => { | |
this.utility.getWebPhoneWindowReference(); | |
MightyCallWebPhoneCore.Phone.HangUp(); | |
}; | |
PhoneMute = () => { | |
this.utility.getWebPhoneWindowReference(); | |
MightyCallWebPhoneCore.Phone.Mute(); | |
}; | |
PhoneUnMute = () => { | |
this.utility.getWebPhoneWindowReference(); | |
MightyCallWebPhoneCore.Phone.UnMute(); | |
}; | |
PhoneHold = () => { | |
this.utility.getWebPhoneWindowReference(); | |
MightyCallWebPhoneCore.Phone.Hold(); | |
}; | |
PhoneUnHold = () => { | |
this.utility.getWebPhoneWindowReference(); | |
MightyCallWebPhoneCore.Phone.UnHold(); | |
}; | |
initLocalStorageListener = () => { | |
this.utility.addEventHandler('storage', this.handleNotifications); | |
}; | |
} | |
class MightyCallWebPhone { | |
public Phone = new MightyCallPhone(); | |
public Profile = new MightyCallProfile(); | |
protected utility = new Utility(); | |
protected id: string; | |
protected debug = false; | |
constructor() { | |
this.id = this.utility.guid(); | |
this.initLocalStorageListener(); | |
} | |
enableDebug = (isEnable) => { | |
this.debug = isEnable !== false; | |
}; | |
ApplyConfig = (cfg: Config) => { | |
console.log(`apply config: ${JSON.stringify(cfg)}`); | |
INTEGRATION_CONFIG = cfg; | |
}; | |
ApplySDKConfig = (cfg: Record<string, unknown>) => { | |
SDK_CONFIG = cfg; | |
}; | |
handleNotifications = (event) => { | |
if (event.key == MIGHTYCALL_EVENT) { | |
const data = JSON.parse(event.newValue); | |
this.fireEvent(data); | |
} | |
}; | |
fireEvent = (data) => { | |
try { | |
if (this[data.type] != undefined && this[data.type][data.event] != undefined) { | |
this[data.type][data.event].fire(data.info); | |
} | |
} catch (exc) { | |
console.warn(`error firing ${data.type} ${data.event}`); | |
console.warn(exc); | |
} | |
}; | |
initLocalStorageListener = () => { | |
this.utility.addEventHandler('storage', this.handleNotifications); | |
}; | |
} | |
const mightyCallWebPhone = new MightyCallWebPhone(); | |
export default mightyCallWebPhone; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment