andrerpena / chatjs

Platform-independent jQuery plugin for chatting
MIT License
184 stars 91 forks source link

SignalR Hub #19

Open rpaschoal opened 9 years ago

rpaschoal commented 9 years ago

Hi Everyone!

Do you guys have the Hub Server code? It would be useful to understand how to get the SignalR adapter running!

irfan-yusanif commented 9 years ago

hi if you have the code please share a sample.

rpaschoal commented 9 years ago

Hello Watoo, I managed to get it working, but it has some changes. Specially because there are bugs in this code.

It was a freelancer project and it has been a while since I don't work with that. I can share my SignalR Hub implementation when I get home.

Cheers!

rpaschoal commented 9 years ago

Here is my adapter code in TypeScript connecting to my SignalR Hub:

/// /// /// /// ///

interface IChatYatClient { sendMessage: (message: ChatMessageInfo) => void; sendTypingSignal: (typingSignal: ChatTypingSignalInfo) => void; userListChanged: (userListChangedInfo: ChatUserListChangedInfo) => void roomListChanged: (roomListChangedInfo: ChatRoomListChangedInfo) => void }

interface IChatYatServer { sendMessage: (roomId: number, conversationId: number, otherUserId: number, messageText: string, clientGuid: string) => JQueryPromise; sendTypingSignal: (roomId: number, conversationId: number, userToId: number) => JQueryPromise; getMessageHistory: (roomId: number, conversationId: number, otherUserId: number) => JQueryPromise; getUserInfo: (userId: number) => JQueryPromise; getUserList: (roomId: number, conversationId: number) => JQueryPromise; enterRoom: (roomId: number) => JQueryPromise; leaveRoom: (roomId: number) => JQueryPromise; getRoomsList(): JQueryPromise; fecharAtendimento: (otherUserId: number) => JQueryPromise; }

interface Window { YatHubReady: JQueryPromise; //chatJs: ChatWindow; }

class YatServerAdapter implements IServerAdapter {

constructor(chatHubServer: HubProxy, chatClientAdapter: IClientAdapter) {
    this.hubServer = chatHubServer;
    this.clientAdapter = chatClientAdapter;
}

// sends a message to a room, conversation or user
sendMessage(roomId: number, conversationId: number, otherUserId: number, messageText: string, clientGuid: string, done: () => void): void {
    var mensagem = { UsuarioId: otherUserId, Texto: messageText };
    var token = $('#Token').val();

    var bounceMessage = new ChatMessageInfo();
    bounceMessage.UserFromId = 0;
    bounceMessage.UserToId = otherUserId;
    bounceMessage.RoomId = roomId;
    bounceMessage.ConversationId = conversationId;
    bounceMessage.Message = messageText;
    bounceMessage.ClientGuid = clientGuid;

    var _this = this;
    this.hubServer.invoke('enviar', token, mensagem).done(function () {
        _this.mudarStatus(otherUserId, 3);
        _this.clientAdapter.triggerMessagesChanged(bounceMessage);
        done();
    });
}

// sends a typing signal to a room, conversation or user
sendTypingSignal(roomId: number, conversationId: number, userToId: number, done: () => void): void {
    done();
}

// gets the message history from a room, conversation or user
getMessageHistory(roomId: number, conversationId: number, otherUserId: number, done: (messages: Array<ChatMessageInfo>) => void): void {
    this.hubServer.invoke('obterHistorico', $('#Token').val(), otherUserId).done(function (messageHistory) {
        done(messageHistory);
    });
}

// gets the given user info
getUserInfo(userId: number, done: (userInfo: ChatUserInfo) => void): void {
    this.hubServer.invoke('getUserInfo', $('#Token').val(), userId).done(function (userInfo) {
        done(userInfo);
    });
}

// gets the user list in a room or conversation
getUserList(roomId: number, conversationId: number, done: (userList: Array<ChatUserInfo>) => void): void {
    this.hubServer.invoke('listarUsuariosEmAtendimento', $('#Token').val()).done(function (userList) {
        done(userList);
    });
}

// gets the rooms list
getRoomsList(done: (roomsList: Array<ChatRoomInfo>) => void) {
    done(new Array <ChatRoomInfo>());
}

// enters the given room
enterRoom(roomId: number, done: () => void) {
    done();
}

// leaves the given room
leaveRoom(roomId: number, done: () => void) {
    done();
}

// Fecha um atendimento
fecharAtendimento(otherUserId: number, done: (userList: Array<ChatUserInfo>) => void): void {
    var _this = this;
    var token = $('#Token').val();

    this.hubServer.invoke('fecharAtendimento', token, otherUserId).done(function (userList) {
        //_this.clientAdapter.triggerUserListChanged(userList); //Já retorna a lista atualizada de atendimentos ativos.
        done(userList);
    });
}

// sends a typing signal to a room, conversation or user
mudarStatus(otherUserId: number, status: number): void {
    var token = $('#Token').val();
    this.hubServer.invoke('mudarStatus', token, otherUserId, status);
}

hubServer: HubProxy;
clientAdapter: IClientAdapter;

}

class YatClientAdapter implements IClientAdapter {

constructor(chatHubClient: HubProxy) {
    this.registeredListernersIds = [];
    this.messagesChangedHandlers = [];
    this.typingSignalReceivedHandlers = [];
    this.userListChangedHandlers = [];
    this.roomListChangedHandlers = [];
    this.hubClient = chatHubClient;
    this.handlersIndex = -1;

    var _this = this;
    // called by the server when a new message arrives
    this.hubClient.on('NotificarMensagem', function (message) {
        var token = $('#Token').val();
        var bounceMessage = new ChatMessageInfo();
        bounceMessage.UserFromId = message.UsuarioId;
        bounceMessage.UserToId = message.RemetenteId;
        bounceMessage.Message = message.Texto;
        //bounceMessage.ClientGuid = message.Id;

        console.log(bounceMessage);

        _this.triggerMessagesChanged(bounceMessage);

        _this.hubClient.invoke('mudarStatus', token, message.UsuarioId, 2);
    });

    //this.hubClient.sendTypingSignal = (typingSignal: ChatTypingSignalInfo) => {
    //    this.triggerTypingSignalReceived(typingSignal);
    //};

    //this.hubClient.userListChanged = (userListChangedInfo: ChatUserListChangedInfo) => {
    //    this.triggerUserListChanged(userListChangedInfo);
    //};

    //this.hubClient.roomListChanged = (roomListChangedInfo: ChatRoomListChangedInfo) => {
    //    this.triggerRoomListChanged(roomListChangedInfo);
    //};
}

// adds a handler to the messagesChanged event
onMessagesChanged(userId: number, handler: (message: ChatMessageInfo) => void): void {
    var indiceRegistrado = -1;

    for (var i = 0; i < this.registeredListernersIds.length; i++) {
        if (this.registeredListernersIds[i] === userId) {
            indiceRegistrado = i;
        }
    }

    if (indiceRegistrado >= 0) {
        this.registeredListernersIds.splice(indiceRegistrado, 1);
        this.messagesChangedHandlers.splice(indiceRegistrado, 1);
        console.log("Índice previamente registrado sendo removido. Valor => " + indiceRegistrado);   
    }
    this.registeredListernersIds.push(userId);
    this.messagesChangedHandlers.push(handler);
}

// adds a handler to the typingSignalReceived event
onTypingSignalReceived(handler: (typingSignal: ChatTypingSignalInfo) => void): void {
    this.typingSignalReceivedHandlers.push(handler);
}

// adds a handler to the userListChanged event
onUserListChanged(handler: (userListData: ChatUserListChangedInfo) => void): void {
    this.userListChangedHandlers.push(handler);
}

// adds a handler to the roomListChanged
onRoomListChanged(handler: (roomListData: ChatRoomListChangedInfo) => void): void {
    this.roomListChangedHandlers.push(handler);
}

triggerMessagesChanged(message: ChatMessageInfo): void {
    for (var i = 0; i < this.messagesChangedHandlers.length; i++)
        this.messagesChangedHandlers[i](message);
}

triggerTypingSignalReceived(typingSignal: ChatTypingSignalInfo): void {
    for (var i = 0; i < this.typingSignalReceivedHandlers.length; i++)
        this.typingSignalReceivedHandlers[i](typingSignal);
}

triggerUserListChanged(userListChangedInfo: ChatUserListChangedInfo): void {
    for (var i = 0; i < this.userListChangedHandlers.length; i++)
        this.userListChangedHandlers[i](userListChangedInfo);
}

triggerRoomListChanged(roomListChangedInfo: ChatRoomListChangedInfo): void {
    for (var i = 0; i < this.roomListChangedHandlers.length; i++)
        this.roomListChangedHandlers[i](roomListChangedInfo);
}

// event handlers
registeredListernersIds: Array<number>;
messagesChangedHandlers: Array<(message: ChatMessageInfo) => void>;
typingSignalReceivedHandlers: Array<(typingSignal: ChatTypingSignalInfo) => void>;
userListChangedHandlers: Array<(userListData: ChatUserListChangedInfo) => void>;
roomListChangedHandlers: Array<(roomListData: ChatRoomListChangedInfo) => void>;

// hub client
hubClient: HubProxy;
handlersIndex: number;

}

class YatAdapterOptions { // the name of the ChatJS SignalR hub in the server. Default is chatHub hubUrl: string; hubName: string; }

class YatAdapter implements IAdapter {

constructor(options: YatAdapterOptions) {
    var defaultOptions = new YatAdapterOptions();
    defaultOptions.hubUrl = "chatHub";
    defaultOptions.hubName = "mensagemHub";
    this.options = $.extend({}, defaultOptions, options);
}

init(done: () => void) {
    var _this = this;
    var connection = $.hubConnection();
    connection.url = this.options.hubUrl;
    this.hub = connection.createHubProxy(this.options.hubName);

    // Esta linha abaixo permite chamada de cross origin pelo chrome.
    connection.start({ jsonp: true }).done(function () {
        console.log('Iniciando comunicação Signalr do Chat. HUB Responsável: MensagemHub.');
        _this.hub.invoke('signOn', $('#Token').val());
        done();
    });

    this.client = new YatClientAdapter(this.hub);
    this.server = new YatServerAdapter(this.hub, this.client);

    //if (!window.chatJsHubReady)
    //    window.chatJsHubReady = $.connection.hub.start();

    //window.chatJsHubReady.done(() => {
    //    // function passed by ChatJS to the adapter to be called when the adapter initialization is completed
    //    done();
    //});
}

// functions called by the server, to contact the client
client: IClientAdapter;

// functions called by the client, to contact the server
server: IServerAdapter;
hub: HubProxy;
options: YatAdapterOptions;

}

rpaschoal commented 9 years ago

In .TXT to improve readability.

jquery.chatjs.adapter.yat.txt

Cheers!

chadboettcher commented 8 years ago

@rpaschoal, do you have example C# code for this? Much appreciated.

Chad

Edit: I found the original examples here: https://github.com/andrerpena/chatjs10.

rpaschoal commented 8 years ago

Cool @chadboettcher !

Nlaskoski2009 commented 8 years ago

I noticed there already is a SignalR adapter in ChatJs/js that does not work. I have gotten SignalR 2.0 working with chatjs 1.0 and a ChatHub similar to this demo: https://github.com/andrerpena/chatjs10/tree/master/Samples/ChatJsWebFormsSample

but haven't been able to replicate it with this new version. Any suggestions?

vkelman commented 8 years ago

Guys, does someone have a working SignalR example with this version of ChatJs?

vkelman commented 8 years ago

@rpaschoal and @andrerpena ,

Apparently, code written by rpaschoal was merged into chatjs and it made it unusable. Multiple errors, undefined things like "YatServerAdapter" inside chatjs\ChatJs\js\jquery.chatjs.messageboard.ts , multiple instances of Portuguese in method names and comments, Typescript not corresponding to JavaScript, etc.

Is there a chance some of you return to this project and make it workable again?

rpaschoal commented 8 years ago

Hello @vkelman,

Sorry about the portuguese messages that were left over. I was using this on a project and just wanted to contribute with many bug fixes I applied to the existing plugin.

I am not sure what you mean by JS not matching TS as you should compile the TS and get the outputted JS as per TS code.

The only big issue I see now in the code is the "YatServerAdapter" type inside the messageboard ts file. That needs a fix and needs to be changed to the adapter interface. Could you push a fix for this one?

Thanks!

rpaschoal commented 8 years ago

@vkelman,

I had a quick look and to fix the undefined error message we just have to remove lines 56 to 61 on the messageboard.ts file.

I will make a pull request for this soon.

rpaschoal commented 8 years ago

@vkelman and @andrerpena ,

I created a pull request that removed the custom adapter code from the messageboard TS file.

I also realised what @vkelman means by difference between TS and JS. @andrerpena could you please build the project again on a typescript compiler and update the JS files available here?

Thanks!

vkelman commented 8 years ago

@rpaschoal ,

I understand that during successful compilation existing .js files should be replaced by once generated by Typescript compiler. I just meant that [some of] current .js files in Github repository were not produced from current .ts files - they are different.

Yes, I already tried to comment out lines 56-61 of messageboard.ts file, although I wasn't sure it's right.

But I'm still getting multiple compilation errors (it's possible that they are not independent). Error 3 Property 'fecharAtendimento' does not exist on type 'IServerAdapter' chatjs\ChatJs\js\jquery.chatjs.userlist.ts 103 What is it? I suppose this was added by you.

Could you help me to resolve the following:

Error 1 Property 'autosize' does not exist on type 'JQuery' chatjs\ChatJs\js\jquery.chatjs.messageboard.ts 63 This is strange: I added /// <reference path="../../Scripts/Typings/jquery.autosize/jquery.autosize.d.ts"/> to the top of this file. So, what's wrong?

Error 2 Supplied parameters do not match any signature of call target. chatjs\ChatJs\js\jquery.chatjs.messageboard.ts 91 Don't understand it.

Error 4 Supplied parameters do not match any signature of call target. chatjs\ChatJs\js\jquery.chatjs.controller.ts 85

Error 5 Cannot find name 'chatJs'. chatjs\ChatJs\js\jquery.chatjs.controller.ts 111

vkelman commented 8 years ago

@rpaschoal and @andrerpena ,

Just to confirm I did a correct thing: On the top of jquery.chatjs.messageboard.ts is the followng: /// <reference path="../../Scripts/Typings/autosize/autosize.d.ts"/> But NuGet command Install-Package jquery.autosize.TypeScript.DefinitelyTyped installs it to a different path: chatjs\Scripts\typings\jquery.autosize\jquery.autosize.d.ts So, I modified that top line of jquery.chatjs.messageboard.ts to be /// <reference path="../../Scripts/Typings/jquery.autosize/jquery.autosize.d.ts"/> Correct? Incorrect? Could it be a reason I'm getting that compilation error mentioned before Error 1 Property 'autosize' does not exist on type 'JQuery'

rpaschoal commented 8 years ago

@vkelman ,

I also removed the "fecharAtendimento" dependency on the userlist.ts file on the latest pull request.

Now we have to wait for @andrerpena. JS files need to be built again and updated here.

About they typings I have no idea, maybe @andrerpena could clarify it more to you. I just initially contributed with the repo to push some bug fixes (Like one that duplicated the messages on the chat).

Thanks!

vkelman commented 8 years ago

@rpaschoal - thank you. I grabbed your updated jquery.chatjs.userlist.ts, it eliminates that error.

I'm still puzzled by the following. Maybe there are some missing references on the tops of jquery.chatjs.controller.ts and jquery.chatjs.messageboard.ts

Error 1 Supplied parameters do not match any signature of call target. chatjs\ChatJs\js\jquery.chatjs.controller.ts 85

Error 2 Cannot find name 'chatJs'. chatjs\ChatJs\js\jquery.chatjs.controller.ts 111

Error 3 Property 'autosize' does not exist on type 'JQuery'. chatjs\ChatJs\js\jquery.chatjs.messageboard.ts 63

Error 4 Supplied parameters do not match any signature of call target. chatjs\ChatJs\js\jquery.chatjs.messageboard.ts 91

vkelman commented 8 years ago

In particular, Error 2 Cannot find name 'chatJs'. chatjs\ChatJs\js\jquery.chatjs.controller.ts 111 is pretty obvious: there is no such object as "chatJs" defined in this file. It cannot work this way. But what object should it be?

@rpaschoal - it was you in "Changes to many fixes found on last year. Eg: Duplicated messages whe..." in what you committed on April 20 - you introduced that code in chatjs.controller.ts 111 which has undefined "chatJs". Could you look, please?

rpaschoal commented 8 years ago

@vkelman,

I could have a look on that in a few days, at the moment I am preparing a big presentation at work and preparing myself for a trip which I will do shortly.

Appreciate if you could have a look into this with us...

Also when I did that check in ages ago I didn't expect that Andre would just merge without any criteria lol

Cheers!

vkelman commented 8 years ago

@rpaschoal - I definitely don't blame you in anything, but rather thankful for your help. I'm trying to choose between several possible initial chat solutions, then I would need to modify my choice to suit our company needs.