diff --git a/assets/js/api.js b/assets/js/api.js index 58f2a61..32286f0 100644 --- a/assets/js/api.js +++ b/assets/js/api.js @@ -1,221 +1,228 @@ import {Socket, LongPoll, Presence} from "phoenix" import UserListWidget from "./widgets/userlist" import UserStatusWidget from "./widgets/userstatus" import ChatInputWidget from "./widgets/chatinput" import ChatRoomWidget from "./widgets/chatroom" class KolabChat { /** * Configuration parameters: * - token: User session token * - context: KolabChat instance identifier * - roomId: Chat room Id to join in * - userListElement: Id of HTML element where to put userslist widget * - userStatusElement: Id of HTML element where to put users status widget * - chatInputElement: Id of HTML element which is a text chat input * - chatRoomElement: Id of HTML element where to put text conversation */ constructor(config) { this.config = config || {} if (!this.config.context) this.config.context = location.hostname; } /** * Initialize WebSocket communication */ init(config) { if (config) this.config = KolabChat.extend(this.config, config) this.initWidgets() // TODO: for integration with external systems we'll use configurable full wss:// url this.socket = new Socket("/socket", { params: {token: this.config.token, context: this.config.context}, logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }), }) this.socket.onOpen(e => { // when connected start using 'system' channel // for users' presence this.initPresence() if (this.config.roomId) { this.initRoom(this.config.roomId) } }) this.socket.connect() } /** * Initializes configured UI widgets */ initWidgets() { let config if (this.config.userListElement && $('#' + this.config.userListElement).length) { config = { username: this.username, openChat: (e, user) => { this.openChat(e, user) } } this.userListWidget = new UserListWidget(this.config.userListElement, config) } if (this.config.userStatusElement && $('#' + this.config.userStatusElement).length) { config = { username: this.username, statusChange: status => { this.setStatus(status) } } this.userStatusWidget = new UserStatusWidget(this.config.userStatusElement, config) } if (this.config.chatRoomElement && $('#' + this.config.chatRoomElement).length) { this.chatRoomWidget = new ChatRoomWidget(this.config.chatRoomElement) } if (this.config.chatInputElement && $('#' + this.config.chatInputElement).length) { config = { submit: (e, msg) => { this.sendTxtMessage(e, msg) } } this.chatInputWidget = new ChatInputWidget(this.config.chatInputElement, config) } } /** * Initialize user presence * Create users list and status widgets */ initPresence() { this.system = this.socket.channel("system", {context: this.config.context}) this.system.on("info", info => { this.username = info.user if (this.userListWidget) { this.userListWidget.setUsername(this.username) } }) this.system.on("presence_state", state => { this.presences = Presence.syncState({}, state) this.renderPresences(this.presences) }) this.system.on("presence_diff", diff => { // ignore initial presence_diff result, handle presence_state first if (this.presences !== undefined) { this.presences = Presence.syncDiff(this.presences, diff) this.renderPresences(this.presences) } }) this.system.join() } /** * Initialize chat channel */ initRoom(roomId) { this.chat = this.socket.channel("room:" + roomId) this.chat.on("new:message", message => { this.chatRoomWidget.append(message.user, message.body) }) this.chat.join() } /** * Send text message to the chat room */ sendTxtMessage(event, message) { this.chat.push("new:message", { body: message }) } /** * Handler for presence responses */ renderPresences(presences) { let userPresence if (this.userStatusWidget && (userPresence = presences[this.username])) { userPresence = this.listBy(this.username, userPresence, this.config.context) this.userStatusWidget.render(userPresence) } if (this.userListWidget) { presences = Presence.list(presences, this.listBy) this.userListWidget.render(presences) } } listBy(user, {metas: metas}, context) { let statusWeights = { offline: 0, busy: 10, away: 20, online: 30 } // Find "best" availability status for the user // If set, narrow the result to the current session context let mostAvailableStatus = metas.reduce((best, meta) => { if (context && context != meta.context) return best return statusWeights[best] > statusWeights[meta.status] ? best : meta.status }, "offline") return { user: user, status: mostAvailableStatus } } /** * User status change */ setStatus(status) { this.system.push('set-status', {status: status}); } /** * Open chat window (and create a new chat room) */ openChat(event, user) { - // TODO: Use 'system' channel to create a chat room first - let roomId = "lobby" + let windowName = 'KolabChat' + new Date().getTime() + let url = "/chat/?token=" + encodeURIComponent(this.config.token) + + var extwin = window.open(url, windowName); + } + /** + * Open a chat window to an existing chat + */ + openExistingChat(event, user, roomId) + { let windowName = 'KolabChat' + new Date().getTime() let url = "/chat/" + encodeURIComponent(roomId) + "/?token=" + encodeURIComponent(this.config.token) var extwin = window.open(url, windowName); } - static extend(obj, src) { Object.keys(src).forEach(function(key) { obj[key] = src[key] }) return obj } } export default KolabChat