ChatController.js 4.93 KB
import '../common/jquery.litelay';

const ChatController = function ($scope, chat, $element) {
    /**
     * Cache chat elements.
     */
    var chatScreen = $element.find('.chat-screen'),
        chatMessages = $element.find('.chat-messages'),
        chatInput = $element.find('.chat-input textarea'),
        chatViewPort = $element.find('.chat-viewport');


    // Display chat loading message.
    chatViewPort.litelay({message: 'Trying to connect to chat server...', spinner: true});

    // Set .chat-screen height to ensure it fits into the window.
    // Do the same on window resize.
    setChatScreenSize();
    $(window).on('resize', setChatScreenSize);

    // Connect to chat server
    chat.connect();

    /**
     * Handle `enter` key on the chat input box.
     */
    chatInput.keydown(function (e) {
        if (e.which === 13) {
            e.preventDefault();
            $scope.chat();
        }
    });

    /**
     * Sends a chat message that is styped into the chat input box.
     */
    $scope.chat = function () {
        if ($scope.msg.trim() === '') return;

        if ($scope.msg.length > 200) {
            return renderSystemMessage({ content: 'Your chat message is longer than 200 characters limit. Please revise it before sending again.' });
        }

        chat.say($scope.msg, 'global');

        chatInput.controller('ngModel').$setViewValue('');
        chatInput.controller('ngModel').$render();
    };

    /**
     * Handle operations when chat has connected.
     */
    chat.on('connect', function () {
        // Remove loading message.
        if (chatViewPort.data('litelay')) {
            chatViewPort.litelay({off: true});
        }
    });

    /**
     * Handle disconnections from socket.
     */
    chat.on('disconnect', function () {
        // Display chat connection lost message.
        chatViewPort.litelay({message: 'Connection to chat server is lost.<br>Trying to reconnect you...', spinner: true});
    });

    /**
     * Render chat when it arrives.
     */
    chat.on('chat', function (chat) {
        renderChatMessage(chat);
    });

    /**
     * Render most recent chats when they arrive.
     */
    chat.on('recent-chats', function (chats) {
        chatMessages.html('');
        _(chats).each(renderChatMessage);
    });

    /**
     * Update user list when one comes.
     */
    chat.on('user-list', function (userList) {
        $scope.userList = userList;
        $scope.userListLength = _(userList).size();
        $scope.user = $scope.userList[DataStore.user.username];

        if ($scope.user === undefined) {
            $element.find('.chat-composer').mousedown(function (e) {
                chatViewPort.litelay({message: 'You must sign in before you can chat.<p><a href="/signup/">Please create a FootyRoom account if you don\'t have one.</a>'});

                $element.one('click', function () {
                    chatViewPort.litelay({off: true});
                });
            });
        }

        $scope.$apply();
    });

    /**
     * Handle system messages.
     */
    chat.on('system', function (message) {
        renderSystemMessage(message);
    });

    /**
     * Renders a message from the chat onto the chat screen.
     *
     * @param  {Object} chat
     */
    function renderChatMessage(chat) {
        renderMessage(
            '<li class="chat-message">' +
                ((chat.userRole >= 20) ? '<span class="icn-whistle badge" title="Moderator"></span>' : '') +
                '<a href="/profile/' + chat.username + '" target="_blank" class="username" style="color: ' + chat.chatColor + '">' + chat.username + ': </a>' +
                '<span class="message">' + chat.msg + '</span>' +
            '</li>'
        );
    }

    /**
     * Render a system message on the chat screen.
     *
     * @param  {Object} message
     */
    function renderSystemMessage(message) {
        renderMessage(
            '<li class="chat-message">' +
                '<span class="message">' + message.content + '</span>' +
            '</li>'
        );
    }

    /**
     * Renders a message on the chat screen.
     *
     * @param  {String} message HTML to append to chat screen.
     */
    function renderMessage(message) {
        var scrollHeight = chatMessages.prop('scrollHeight');

        chatMessages.append(message);

        if (scrollHeight === (chatMessages.outerHeight() + chatMessages.scrollTop())) {
            chatMessages.scrollTop(chatMessages.prop('scrollHeight'));
        }
    }

    /**
     * Sets .chat-screen height to ensure it fits into the window.
     */
    function setChatScreenSize() {
        // TODO: what are these 146 1 ?? Do something about it.
        chatScreen.css('height', $(window).height() - 146 - 1);
    }

    /**
     * Sets users color.
     *
     * @param {String} color
     */
    $scope.setUserColor = function (color) {
        chat.emit('set-color', color);
    };
};

ChatController.$inject = ['$scope', 'chat', '$element'];
export default ChatController;