diff --git a/file/js/be.bastelstu.Chat.litcoffee b/file/js/be.bastelstu.Chat.litcoffee index 343b91b..d3e76a8 100644 --- a/file/js/be.bastelstu.Chat.litcoffee +++ b/file/js/be.bastelstu.Chat.litcoffee @@ -63,7 +63,7 @@ exposed by a function if necessary. Initialize **Tims Chat**. Bind needed DOM events and initialize data structures. initialized = false - init = (config, titleTemplate, messageTemplate, userTemplate) -> + init = (roomID, config, titleTemplate, messageTemplate, userTemplate) -> return false if initialized initialized = true @@ -240,7 +240,6 @@ Toggle fullscreen mode. $('html').addClass 'fullscreen' else $('html').removeClass 'fullscreen' - Toggle checkboxes @@ -254,9 +253,9 @@ Visibly mark the message once the associated checkbox is checked. $(document).on 'click', '.timsChatMessage :checkbox', (event) -> if $(@).is ':checked' - $(@).parents('.timsChatMessage').addClass('jsMarked') + $(@).parents('.timsChatMessage').addClass 'jsMarked' else - $(@).parents('.timsChatMessage').removeClass('jsMarked') + $(@).parents('.timsChatMessage').removeClass 'jsMarked' Scroll down when autoscroll is being activated. @@ -297,13 +296,10 @@ Ask for permissions to use Desktop notifications when notifications are activate events.newMessage.add notify -Initialize the `PeriodicalExecuter`s and run them once. +Initialize the `PeriodicalExecuter`s pe.refreshRoomList = new WCF.PeriodicalExecuter refreshRoomList, 60e3 pe.getMessages = new WCF.PeriodicalExecuter getMessages, v.config.reloadTime * 1e3 - refreshRoomList() - getMessages() - Initialize the [**nodePush**](https://github.com/wbbaddons/nodePush) integration of **Tims Chat**. Once the browser is connected to **nodePush** periodic message loading will be disabled and **Tims Chat** will @@ -322,8 +318,9 @@ load messages if the appropriate event arrives. be.bastelstu.wcf.nodePush.onMessage 'be.bastelstu.chat.newMessage', getMessages be.bastelstu.wcf.nodePush.onMessage 'be.bastelstu.wcf.nodePush.tick60', getMessages -Finished! Enable the input now. +Finished! Enable the input now and join the chat. + join roomID $('#timsChatInput').enable().jCounter().focus(); console.log "Finished initializing" @@ -531,7 +528,6 @@ Fetch the roomlist from the server and update it in the GUI. refreshRoomList = -> console.log 'Refreshing the roomlist' - $('#toggleRooms .ajaxLoad').show() new WCF.Action.Proxy autoSend: true @@ -541,14 +537,13 @@ Fetch the roomlist from the server and update it in the GUI. showLoadingOverlay: false suppressErrors: true success: (data) -> - $('#timsChatRoomList li').remove() - $('#toggleRooms .ajaxLoad').hide() + $('.timsChatRoom').remove() $('#toggleRooms .badge').text data.returnValues.length for room in data.returnValues li = $ '
' li.addClass 'active' if room.active - $("""#{room.title}""").addClass('timsChatRoom').appendTo li + $("""#{room.title}""").addClass('timsChatRoom').data('roomID', room.roomID).appendTo li $('#timsChatRoomList ul').append li if window.history?.replaceState? @@ -557,43 +552,10 @@ Fetch the roomlist from the server and update it in the GUI. target = $(@) window.history.replaceState {}, '', target.attr 'href' - - $.ajax target.attr('href'), - dataType: 'json' - data: - ajax: 1 - type: 'POST' - success: (data, textStatus, jqXHR) -> - loading = false - target.parent().removeClass 'loading' - - $('.active .timsChatRoom').parent().removeClass 'active' - target.parent().addClass 'active' - - $('#timsChatTopic').text data.topic - if data.topic is '' - $('#timsChatTopic').addClass 'empty' - else - $('#timsChatTopic').removeClass 'empty' - - $('.timsChatMessage').addClass 'unloaded' - - handleMessages data.messages - - document.title = v.titleTemplate.fetch data - -Reload the whole page when an error occurs. The users thus sees the error message (usually `PermissionDeniedException`) - - error: -> - window.location.reload true - -Show loading icon and prevent switching the room in parallel. - - beforeSend: -> - return false if target.parent().hasClass('loading') or target.parent().hasClass 'active' - - loading = true - target.parent().addClass 'loading' + + join target.data 'roomID' + $('#timsChatRoomList .active').removeClass 'active' + target.parent().addClass 'active' console.log "Found #{data.returnValues.length} rooms" @@ -621,8 +583,37 @@ Shows an unrecoverable error with the given text. $('#timsChatLoadingErrorDialog').wcfDialog closable: false - title: WCF.Language.get('wcf.global.error.title') + title: WCF.Language.get 'wcf.global.error.title' +Joins a room. + + join = (roomID) -> + loading = true + new WCF.Action.Proxy + autoSend: true + data: + actionName: 'join' + className: 'chat\\data\\room\\RoomAction' + parameters: + roomID: roomID + success: (data) -> + loading = false + + $('#timsChatTopic').text data.returnValues.topic + if data.topic is '' + $('#timsChatTopic').addClass 'empty' + else + $('#timsChatTopic').removeClass 'empty' + + $('.timsChatMessage').addClass 'unloaded' + + document.title = v.titleTemplate.fetch data.returnValues + handleMessages data.returnValues.messages + getMessages() + refreshRoomList() + failure: -> + showError WCF.Language.get 'chat.error.join' + Bind the given callback to the given event. addListener = (event, callback) -> @@ -645,7 +636,7 @@ And finally export the public methods and variables. refreshRoomList: refreshRoomList insertText: insertText freeTheFish: freeTheFish - handleMessages: handleMessages + join: join listener: add: addListener remove: removeListener diff --git a/file/lib/data/room/Room.class.php b/file/lib/data/room/Room.class.php index c9d8cff..b60a844 100644 --- a/file/lib/data/room/Room.class.php +++ b/file/lib/data/room/Room.class.php @@ -93,7 +93,7 @@ public function canWrite(\wcf\data\user\User $user = null) { } /** - * Returns the ID of this chat-room. + * Returns the ID of this chatroom. * * @see \wcf\system\request\IRouteController */ @@ -102,7 +102,7 @@ public function getID() { } /** - * Returns the name of this chat-room. + * Returns the name of this chatroom. * * @see \wcf\system\request\IRouteController */ @@ -110,6 +110,15 @@ public function getTitle() { return \wcf\system\WCF::getLanguage()->get($this->title); } + /** + * Returns the topic of this chat room + * + * @return string + */ + public function getTopic() { + return \wcf\system\WCF::getLanguage()->get($this->topic); + } + /** * Returns the number of users currently active in this room. * diff --git a/file/lib/data/room/RoomAction.class.php b/file/lib/data/room/RoomAction.class.php index e6f9bd8..5368579 100644 --- a/file/lib/data/room/RoomAction.class.php +++ b/file/lib/data/room/RoomAction.class.php @@ -1,6 +1,8 @@ checkPermissions($this->permissionsUpdate); } else { - throw new \wcf\system\exception\PermissionDeniedException(); + throw new exception\PermissionDeniedException(); } if (!isset($this->parameters['data']['structure'])) { - throw new \wcf\system\exception\UserInputException('structure'); + throw new exception\UserInputException('structure'); } } @@ -124,10 +126,10 @@ public function updatePosition() { * Validates parameters and permissions. */ public function validateGetRoomList() { - if (!MODULE_CHAT) throw new \wcf\system\exception\IllegalLinkException(); + if (!MODULE_CHAT) throw new exception\IllegalLinkException(); $this->parameters['room'] = RoomCache::getInstance()->getRoom(WCF::getUser()->chatRoomID); - if ($this->parameters['room'] === null) throw new \wcf\system\exception\IllegalLinkException(); + if ($this->parameters['room'] === null) throw new exception\IllegalLinkException(); } /** @@ -146,6 +148,7 @@ public function getRoomList() { 'application' => 'chat', 'object' => $room )), + 'roomID' => $room->roomID, 'active' => $room->roomID == $this->parameters['room']->roomID ); } @@ -153,39 +156,138 @@ public function getRoomList() { return $result; } + /** + * Validates parameters and permissions. + */ + public function validateJoin() { + if (!MODULE_CHAT) throw new exception\IllegalLinkException(); + + unset($this->parameters['user']); + $this->readInteger('roomID'); + + $room = RoomCache::getInstance()->getRoom($this->parameters['roomID']); + if ($room === null) throw new exception\UserInputException(); + if (!$room->canEnter()) throw new exception\PermissionDeniedException(); + } + + /** + * Joins the room. + */ + public function join() { + // user cannot be set during an AJAX request but may be set by the chat itself + if (!isset($this->parameters['user'])) { + $this->parameters['user'] = WCF::getUser(); + } + + $room = RoomCache::getInstance()->getRoom($this->parameters['roomID']); + if ($room === null) throw new exception\UserInputException(); + + if (CHAT_DISPLAY_JOIN_LEAVE) { + if ($this->parameters['user']->chatRoomID) { + // leave message + $messageAction = new message\MessageAction(array(), 'create', array( + 'data' => array( + 'roomID' => $this->parameters['user']->chatRoomID, + 'sender' => $this->parameters['user']->userID, + 'username' => $this->parameters['user']->username, + 'time' => TIME_NOW, + 'type' => message\Message::TYPE_LEAVE, + 'message' => serialize(array('room' => $room)), + 'color1' => $this->parameters['user']->chatColor1, + 'color2' => $this->parameters['user']->chatColor2 + ) + )); + $messageAction->executeAction(); + } + + $ipAddress = ''; + if ($this->parameters['user']->userID == WCF::getUser()->userID) $ipAddress = \wcf\util\UserUtil::convertIPv6To4(\wcf\util\UserUtil::getIpAddress()); + + // join message + $messageAction = new message\MessageAction(array(), 'create', array( + 'data' => array( + 'roomID' => $room->roomID, + 'sender' => $this->parameters['user']->userID, + 'username' => $this->parameters['user']->username, + 'time' => TIME_NOW, + 'type' => message\Message::TYPE_JOIN, + 'message' => serialize(array('ipAddress' => $ipAddress)), + 'color1' => $this->parameters['user']->chatColor1, + 'color2' => $this->parameters['user']->chatColor2 + ) + )); + $messageAction->executeAction(); + } + + $newestMessages = message\ViewableMessageList::getNewestMessages($room, CHAT_LASTMESSAGES); + + try { + $lastSeen = end($newestMessages)->messageID; + } + catch (\wcf\system\exception\SystemException $e) { + $lastSeen = 0; + } + + $editor = new \wcf\data\user\UserEditor($this->parameters['user']); + $editor->update(array( + 'chatRoomID' => $room->roomID, + 'chatAway' => null, + 'chatLastActivity' => TIME_NOW, + 'chatLastSeen' => $lastSeen + )); + + + // add activity points + $microtime = microtime(true) * 1000; + $result = $microtime & 0xFFFFFFFF; + if ($result > 0x7FFFFFFF) $result -= 0x80000000; + \wcf\system\user\activity\point\UserActivityPointHandler::getInstance()->fireEvent('be.bastelstu.chat.activityPointEvent.join', $result, WCF::getUser()->userID); + + // break if not using ajax + \wcf\system\nodePush\NodePushHandler::getInstance()->sendMessage('be.bastelstu.chat.join'); + + $messages = array(); + foreach ($newestMessages as $message) $messages[] = $message->jsonify(true); + return array( + 'title' => (string) $room, + 'topic' => $room->getTopic(), + 'messages' => $messages + ); + } + /** * Validates parameters and permissions. */ public function validateLeave() { - if (!MODULE_CHAT) throw new \wcf\system\exception\IllegalLinkException(); + if (!MODULE_CHAT) throw new exception\IllegalLinkException(); unset($this->parameters['user']); - if (RoomCache::getInstance()->getRoom(WCF::getUser()->chatRoomID) === null) throw new \wcf\system\exception\IllegalLinkException(); + if (RoomCache::getInstance()->getRoom(WCF::getUser()->chatRoomID) === null) throw new exception\IllegalLinkException(); } /** * Leaves the room. */ public function leave() { - // user cannot be set during an AJAX request may be set by the chat itself + // user cannot be set during an AJAX request but may be set by the chat itself if (!isset($this->parameters['user'])) { $this->parameters['user'] = WCF::getUser(); } $room = RoomCache::getInstance()->getRoom($this->parameters['user']->chatRoomID); - if ($room === null) throw new \wcf\system\exception\UserInputException(); + if ($room === null) throw new exception\UserInputException(); if (CHAT_DISPLAY_JOIN_LEAVE) { // leave message - $messageAction = new \chat\data\message\MessageAction(array(), 'create', array( + $messageAction = new message\MessageAction(array(), 'create', array( 'data' => array( 'roomID' => $room->roomID, 'sender' => $this->parameters['user']->userID, 'username' => $this->parameters['user']->username, 'time' => TIME_NOW, - 'type' => \chat\data\message\Message::TYPE_LEAVE, - 'message' => '', + 'type' => message\Message::TYPE_LEAVE, + 'message' => serialize(array('room' => null)), 'color1' => $this->parameters['user']->chatColor1, 'color2' => $this->parameters['user']->chatColor2 ) diff --git a/file/lib/page/ChatPage.class.php b/file/lib/page/ChatPage.class.php index 47cb50e..d7a5d54 100644 --- a/file/lib/page/ChatPage.class.php +++ b/file/lib/page/ChatPage.class.php @@ -1,6 +1,7 @@ - */ - public $newestMessages = array(); - /** * The current room. * @@ -72,13 +66,6 @@ class ChatPage extends \wcf\page\AbstractPage { */ public $smileyCategories = array(); - /** - * Values read from the UserStorage of the current user. - * - * @var array - */ - public $userData = array(); - /** * @see wcf\page\AbstractPage::$enableTracking */ @@ -91,7 +78,6 @@ public function assignVariables() { parent::assignVariables(); WCF::getTPL()->assign(array( - 'newestMessages' => $this->newestMessages, 'room' => $this->room, 'roomID' => $this->roomID, 'rooms' => $this->rooms, @@ -110,39 +96,6 @@ public function readData() { $this->readRoom(); - if (CHAT_DISPLAY_JOIN_LEAVE) { - $messageAction = new data\message\MessageAction(array(), 'create', array( - 'data' => array( - 'roomID' => $this->room->roomID, - 'sender' => WCF::getUser()->userID, - 'username' => WCF::getUser()->username, - 'time' => TIME_NOW, - 'type' => \chat\data\message\Message::TYPE_JOIN, - 'message' => serialize(array('ipAddress' => \wcf\util\UserUtil::convertIPv6To4(\wcf\util\UserUtil::getIpAddress()))), - 'color1' => WCF::getUser()->chatColor1, - 'color2' => WCF::getUser()->chatColor2 - ) - )); - $messageAction->executeAction(); - $messageAction->getReturnValues(); - } - - $this->newestMessages = data\message\ViewableMessageList::getNewestMessages($this->room, CHAT_LASTMESSAGES); - try { - $lastSeen = end($this->newestMessages)->messageID; - } - catch (\wcf\system\exception\SystemException $e) { - $lastSeen = 0; - } - - $editor = new \wcf\data\user\UserEditor(WCF::getUser()); - $editor->update(array( - 'chatRoomID' => $this->room->roomID, - 'chatAway' => null, - 'chatLastActivity' => TIME_NOW, - 'chatLastSeen' => $lastSeen - )); - // get default smilies if (MODULE_SMILEY) { $this->smileyCategories = \wcf\data\smiley\SmileyCache::getInstance()->getCategories(); @@ -169,7 +122,6 @@ public function readParameters() { parent::readParameters(); if (isset($_REQUEST['id'])) $this->roomID = (int) $_REQUEST['id']; - if (isset($_REQUEST['ajax'])) $this->useTemplate = false; } /** @@ -183,7 +135,7 @@ public function readRoom() { $room = reset($this->rooms); if ($room === null) { // no valid room found - throw new \wcf\system\exception\IllegalLinkException(); + throw new exception\IllegalLinkException(); } // redirect to first chat-room \wcf\util\HeaderUtil::redirect(\wcf\system\request\LinkHandler::getInstance()->getLink('Chat', array( @@ -192,9 +144,9 @@ public function readRoom() { exit; } - if (!isset($this->rooms[$this->roomID])) throw new \wcf\system\exception\IllegalLinkException(); + if (!isset($this->rooms[$this->roomID])) throw new exception\IllegalLinkException(); $this->room = $this->rooms[$this->roomID]; - if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException(); + if (!$this->room->canEnter()) throw new exception\PermissionDeniedException(); } /** @@ -207,26 +159,6 @@ public function show() { WCF::getBreadcrumbs()->remove(0); parent::show(); - - // add activity points - $microtime = microtime(true) * 1000; - $result = $microtime & 0xFFFFFFFF; - if ($result > 0x7FFFFFFF) $result -= 0x80000000; - \wcf\system\user\activity\point\UserActivityPointHandler::getInstance()->fireEvent('be.bastelstu.chat.activityPointEvent.join', $result, WCF::getUser()->userID); - - // break if not using ajax - \wcf\system\nodePush\NodePushHandler::getInstance()->sendMessage('be.bastelstu.chat.join'); - if ($this->useTemplate) exit; - @header('Content-type: application/json'); - - $messages = array(); - foreach ($this->newestMessages as $message) $messages[] = $message->jsonify(true); - echo \wcf\util\JSON::encode(array( - 'title' => $this->room->getTitle(), - 'topic' => WCF::getLanguage()->get($this->room->topic), - 'messages' => $messages - )); - exit; } /** diff --git a/language/de.xml b/language/de.xml index 54fc996..9292a61 100644 --- a/language/de.xml +++ b/language/de.xml @@ -59,6 +59,7 @@