Search code examples
angularxmppangular5strophe

Starting point for an XMPP web client in angular5


I apologize if the question may be too broad, surely because I'm new to XMPP.

I'm developing an Angular6 app and wish to integrate a Jabber chat in it. I've googled a lot but I don't seem to find any clear answer.

Apparently strophe.js looks promising but I cannot find any documentation on how to integrate it in an Angular5/6 project.

Any hint will be greatly appreciated

Thanks


Solution

  • Well, I've found xmpp-bosh-client and ngx-chat.

    The first one is at least documented. The second is not, but I can peek into sources.

    May be this can help someone else in my same boots.

    Thanks

    P.S. If someone knows something better, he/she is most welcome

    EDIT

    I'm posting some code snippet of how I managed to connect to an eJabberd (local) server with strophe.js in a TypeScript/Angular (6.x) frontend.

    chat-panel.service.ts

    import { Injectable } from '@angular/core';
    
    import { Strophe, $pres } from 'strophe.js';
    
    import { EJABBERD } from 'app/api/api.module';
    
    var chatPanelServiceInstance: any = null;
    
    @Injectable()
    export class ChatPanelService
    {
        contacts: any[];
        chats: any[];
        user: any;
        client: any;
    
        // Private
        private _xmppConnectionsString: String = "ws://" + EJABBERD.host + ":5280/ws"; // WebSockets
        //private _xmppConnectionsString: String = "http://" + EJABBERD.host + ":5280/bosh"; // BOSH 
        private _xmppConnection: any = null;
    
        /**
         * Constructor
         *
         * @param {HttpClient} _httpClient
         */
        constructor(
        )
        {
            chatPanelServiceInstance = this;
            Strophe.log = (level: any, msg: string) => { console.log(level + ": " + msg); };
        }
    
        /**
         * Log into eJabberd
         *
         * @param {string} jid      user name
         * @param {string} password password (actually, the user token)
         */
        login(jid: string, password: string): void
        {
            if ( ! this._xmppConnection ) {
                this._xmppConnection = new Strophe.Connection( this._xmppConnectionsString , {'keepalive': true});
            }
    
            // this._xmppConnection.rawInput = (data: any) => {console.log("RAW IN: " + data)};
            // this._xmppConnection.rawOutput = (data: any) => {console.log("RAW OUT: " + data)};
    
            this._xmppConnection.connect(jid+'@'+EJABBERD.host, password, this._onConnect);
        }
    
        /**
         * Disconnect from eJabberd
         */
        logOut(): void
        {
            if ( this._xmppConnection ) {
                this._xmppConnection.options.sync = true;
                this._xmppConnection.flush();
                this._xmppConnection.disconnect("logout");
                this._xmppConnection = null;
            }
        }
    
        /**
         * eJabberd XMPP message Handler
         * @param {string} msg Message received
         */
        private _onMessage(msg: any): boolean
        {
            console.log(msg);
    
            return true;
        }
    
        /**
         * eJabberd connection Handler
         * @param {any} status connection result
         */
        private _onConnect(status: any): void
        {
            switch (status) {
                case Strophe.Status.CONNECTING:
                    console.log("Connecting to eJabberd...");
                    break;
                case Strophe.Status.CONNFAIL:
                    console.log("eJabberd connection failed!");
                    break;
                case Strophe.Status.DISCONNECTING:
                    console.log("Disconnecting from eJabberd...");
                    break;
                case Strophe.Status.DISCONNECTED:
                    console.log("Disconnected from eJabberd");
                    break;
                case Strophe.Status.CONNECTED:
                    // We could have used 'this' instead of an external pointer (chatPanelServiceInstance), 
                    // but the compiler is getting the meaning of 'this' wrong since strophe.js is not a native TypeScript library.
                    // This means that at run time 'this' doesn't point the service instance, rather to the connection itself.
                    // In order to avoid confusion I've chosen to use an explicit pointer to the service. 
                    //
                    chatPanelServiceInstance._xmppConnection.addHandler(chatPanelServiceInstance._onMessage, null, 'message');
    
                    //Setting our presence in the server so that everyone can know that we are online
                    chatPanelServiceInstance._xmppConnection.send($pres().tree());
    
                    console.log("eJabberd connected!");
                    break;
                case Strophe.Status.AUTHENTICATING:
                    console.log("eJabberd authenticating...");
                    break;
                case Strophe.Status.AUTHFAIL:
                    console.log("eJabberd authentication failed!");
                    break;
                case Strophe.Status.ERROR:
                    console.log("eJabberd generic connection error!");
                    break;
                case Strophe.Status.ATTACHED:
                    console.log("eJabberd connection attached!");
                    break;
                case Strophe.Status.REDIRECT:
                    console.log("eJabberd connection redirected!");
                    break;
                case Strophe.Status.CONNTIMEOUT:
                    console.log("eJabberd connection timeout!");
                    break;
                default:
                    console.log("eJabberd: Unknow connection status");
            }
        }
    

    Relevant points:

    1. Note the use of _xmppConnectionString: I'm using Web Sockets to connect but the BOSH version is working fine as well.
    2. Note the use of an external pointer to the service. (chatPanelServiceInstance - see comments in code)
    3. Install strophe.js like this: in the root folder of your angular project, type npm install --save strophe.js