Acrobits IPC SDK is intended to be used by any web based application that is running inside a WebView of an Acrobits Cloudsoftphone native app, to communicate with that native app.
To get started, run:
## npm
npm install @acrobits/ipc-sdk
## pnpm (recommended)
pnpm add @acrobits/ipc-sdk
## yarn
yarn add @acrobits/ipc-sdk
The package is self-contained: it bundles the IPC protocol implementation and its type declarations, and its only dependency is rxjs.
If your project maps the @acrobits scope to another registry (for example in .npmrc), plain @acrobits/ipc-sdk requests go to that registry too. To install the SDK from public npm in such a project, depend on the public tarball URL of the version you need and commit the updated lockfile:
{
"dependencies": {
"@acrobits/ipc-sdk": "https://registry.npmjs.org/@acrobits/ipc-sdk/-/ipc-sdk-0.15.0.tgz"
}
}
The SDK is built using TypeScript so you should have detailed type information for all available methods and properties.
// import the IPCManager
import { IPCManager } from '@acrobits/ipc-sdk';
// create an instance of IPCManager
const manager = new IPCManager();
// check if we're not running under a host context
if ((await manager.determineContext()) !== 'host') {
// we are running in standalone mode or the context couldn't be determined
// handle any cleanup
return;
}
// setup listeners for the badge query and lifecycle events
manager.onBadgeQueryRequest(() => {
// determine the updated badge count
const count = getLatestCountForBadgeFromSomewhere();
// send the badge update to the host
manager.badgeUpdate(count);
});
manager.onLifecycleEvent((eventName: string, payload: <string, unknown>) => {
// do something to handle the lifecycle event
});
// initialize the IPC connection
await manager.initiateConnection();
// update badge count
await manager.badgeUpdate(12);
// match contacts
const matches = await manager.matchContacts([
{
type: 'cloudUsername',
cloudId: 'MY_CLOUD_ID',
cloudUsername: 'myUsername'
},
{
type: 'uri',
cloudId: 'MY_CLOUD_ID',
uri: 'sip:any-sip-uri'
},
{
type: 'uri',
cloudId: 'MY_CLOUD_ID',
uri: 'tel:+1234567890'
}
]);
for (const detailedContact of matches) {
console.log({
cloudId: detailedContact.cloudId,
cloudUsername: detailedContact.cloudUsername,
displayName: detailedContact.displayName,
contactLabel: detailedContact.contactLabel,
type: detailedContact.type,
uri: detailedContact.uri,
profilePictureUrl: detailedContact.profilePictureUrl
});
}
Hosts that negotiate IPC wire protocol version 2.5 or higher (shown by manager.negotiatedVersion, independent of this package's npm version) can translate strings with their own translation framework. On older hosts, translate and onTranslationsChanged throw an UnsupportedVersionError, so call them after initiateConnection and catch the error.
// a translation ID, a translation ID with parameters, or a raw literal that is not translated
const title = await manager.translate('app_name');
const missedCalls = await manager.translate({ key: 'missed_calls', count: 2, args: [2] });
const literal = await manager.translate({ raw: 'Acrobits' });
// `null` means the host could not resolve the request
render(title ?? 'Fallback title');
// the host notifies when its translations change; translate the displayed strings again
const unsubscribe = manager.onTranslationsChanged(async () => {
render((await manager.translate('app_name')) ?? 'Fallback title');
});
The host sends its preferred locales once, right after the handshake. getLocales returns them, most specific first; the manager keeps them, so ask any time after initiateConnection. It resolves with an empty list when the host sends none.
const locales = await manager.getLocales({ timeoutMs: 2000 }); // e.g. ['cs-CZ', 'cs']
Hosts that negotiate IPC wire protocol version 2.4 or higher expose their contact sources (address books and accounts). On older hosts, every method below throws an UnsupportedVersionError.
const controller = new AbortController();
const options = { signal: controller.signal, timeoutMs: 5000 };
// sources, then contacts page by page until totalCount or a short page
const sources = await manager.getContactSources(options);
const page = await manager.getContacts(
{ sourceId: sources[0].sourceId, offset: 0, limit: 500, resultTypes: ['Uri', 'CloudUsername'] },
options
);
// full detail of one contact (null when it is gone), by its { sourceId, id }, and search in one or all sources
const contact = await manager.getContact(page.contacts[0].contactId, options);
const { results, truncated } = await manager.searchContacts({ term: 'Ada', limit: 50 }, options);
// ask the host to refresh a source; progress and changes arrive as events
manager.syncContactSource(sources[0].sourceId);
const unsubscribers = [
manager.onContactSourceSyncState(({ sourceId, state }) =>
showSyncing(sourceId, state === 'inProgress')
),
manager.onContactsUpdated(() => reloadPages()),
manager.onContactSourcesChanged((event) => showSources(event.sources))
];
The requests accept an optional signal and timeoutMs. An aborted signal sends nothing; an abort or a timeout while waiting rejects (with the signal's reason, or an IpcRequestTimeoutError) and stops waiting for the reply. Each entry keeps the host's matchesNumberPattern result, which reflects the app's number pattern; decide yourself what may be called or messaged.
Contact avatars are not exposed yet: avatar is only an asset reference, and the SDK has no public method to fetch it.
The SDK logs message types and ids only, never message content such as contacts, numbers or tokens.
For more details on the available SDK methods and properties, refer to the documentation.