diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 41d1881..0000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: php -php: - - 5.3 -script: php build.php \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..555681d --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +Tims Chat 3.0 +============= + +Tims Chat is a chat-plugin for WoltLab Community Framework. + + +Version notes +------------- + +The currently available source code represents an early alpha-version of Tims Chat, even though it may be installable, we cannot guarantee a working installation at any time. You MUST NOT install and/or use Tims Chat 3.0 in a production environment. + +Contribution +------------ + +Developers are always welcome to fork Tims Chat and provide features or bug fixes using pull requests. If you make changes or add classes it is mandatory to follow the requirements below: + +* Testing is key, you MUST try out your changes before submitting pull requests +* You MUST save your files with Unix-style line endings (\n) +* You MUST NOT include the closing tag of a PHP block at the end of file, provide an empty newline instead +* You MUST use tabs for indentation + * Tab size of 8 is required + * Empty lines MUST be indented equal to previous line +* All comments within source code MUST be written in English language +* Use a sensible number of commits. In most cases one commit should be enough. + * Split huge changes into several logical groups + * Rebase small changes that consist of several commits into one commit + +Follow the above conventions if you want your pull requests accepted. + +License +------- + +For licensing information refer to the LICENSE file in this folder. \ No newline at end of file diff --git a/build.php b/build.php old mode 100644 new mode 100755 index 5439cc6..f10da56 --- a/build.php +++ b/build.php @@ -1,16 +1,74 @@ #!/usr/bin/env php + * @package timwolla.wcf.chat + */ +echo << +(($, window) -> TimWolla.WCF.Chat = titleTemplate: null messageTemplate: null + newMessageCount: null + events: + newMessage: $.Callbacks() + userMenu: $.Callbacks() init: () -> + console.log('[TimWolla.WCF.Chat] Initializing'); @bindEvents() - @refreshRoomList() - new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, this), 60e3 - new WCF.PeriodicalExecuter $.proxy(@getMessages, this), @config.reloadTime * 1000 + @events.newMessage.add $.proxy @notify, @ - $('#chatInput').focus() + new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, @), 60e3 + new WCF.PeriodicalExecuter $.proxy(@getMessages, @), @config.reloadTime * 1000 + @refreshRoomList() + @getMessages() + + console.log '[TimWolla.WCF.Chat] Finished initializing' ### # Binds all the events needed for Tims Chat. ### bindEvents: () -> + @isActive = true + $(window).focus $.proxy () -> + document.title = @titleTemplate.fetch({ title: $('#chatRoomList .activeMenuItem a').text() }) + @newMessageCount = 0 + @isActive = true + , @ + + $(window).blur $.proxy () -> + @isActive = false + , @ + $('.smiley').click $.proxy (event) -> @insertText ' ' + $(event.target).attr('alt') + ' ' - , this + , @ $('.chatSidebarTabs li').click $.proxy (event) -> event.preventDefault() @toggleSidebarContents $ event.target - , this - - $('.chatUser .chatUserLink').click $.proxy (event) -> - event.preventDefault() - @toggleUserMenu $ event.target - , this + , @ $('#chatForm').submit $.proxy (event) -> event.preventDefault() @submit $ event.target - , this + , @ $('#chatClear').click (event) -> event.preventDefault() @@ -50,7 +64,7 @@ TimWolla.WCF ?= {} $('#chatInput').focus() $('.chatToggle').click (event) -> - element = $ this + element = $ @ icon = element.find 'img' if element.data('status') is 1 element.data 'status', 0 @@ -60,6 +74,10 @@ TimWolla.WCF ?= {} element.data 'status', 1 icon.attr 'src', icon.attr('src').replace /disabled(\d?).([a-z]{3})$/, 'enabled$1.$2' element.attr 'title', element.data 'disableMessage' + if typeof window.webkitNotifications isnt 'undefined' + $('#chatNotify').click (event) -> + window.webkitNotifications.requestPermission() + ### # Changes the chat-room. # @@ -86,13 +104,14 @@ TimWolla.WCF ?= {} return if $('#topic').text().trim() is '' $('#topic').wcfBlindOut 'vertical', () -> - $(this).text '' + $(@).text '' else $('#topic').text data.topic - $('#topic').wcfBlindIn() if $('#topic').text().trim() isnt '' + $('#topic').wcfBlindIn() if $('#topic').text().trim() isnt '' and $('#topic').is(':hidden') $('title').text @titleTemplate.fetch(data) - , this) + @getMessages() + , @) error: () -> # reload page to change the room the old fashion-way # inclusive the error-message :) @@ -102,12 +121,13 @@ TimWolla.WCF ?= {} @loading = true target.parent().addClass 'ajaxLoad' - , this) + , @) ### # Frees the fish ### freeTheFish: () -> return if $.wcfIsset('fish') + console.warn '[TimWolla.WCF.Chat] Freeing the fish' fish = $ '
' + WCF.String.escapeHTML('><((((°>') + '
' fish.css position: 'absolute' @@ -120,15 +140,20 @@ TimWolla.WCF ?= {} fish.appendTo $ 'body' new WCF.PeriodicalExecuter(() -> left = (Math.random() * 100 - 50) + top = (Math.random() * 100 - 50) + fish = $('#fish') - $('#fish').text('><((((°>') if (left > 0) - $('#fish').text('<°))))><') if (left < 0) + left *= -1 if((fish.position().left + left) < (0 + fish.width()) or (fish.position().left + left) > ($(document).width() - fish.width())) + top *= -1 if((fish.position().top + top) < (0 + fish.height()) or (fish.position().top + top) > ($(document).height() - fish.height())) - $('#fish').animate - top: '+=' + (Math.random() * 100 - 50) + fish.text('><((((°>') if (left > 0) + fish.text('<°))))><') if (left < 0) + + fish.animate + top: '+=' + top left: '+=' + left , 1000 - , 3e3); + , 1.5e3); ### # Loads new messages. ### @@ -138,7 +163,8 @@ TimWolla.WCF ?= {} type: 'POST' success: $.proxy((data, textStatus, jqXHR) -> @handleMessages(data.messages) - , this) + @handleUsers(data.users) + , @) ### # Inserts the new messages. # @@ -146,6 +172,8 @@ TimWolla.WCF ?= {} ### handleMessages: (messages) -> for message in messages + @events.newMessage.fire message + output = @messageTemplate.fetch message li = $ '
  • ' li.addClass 'chatMessage chatMessage'+message.type @@ -156,6 +184,43 @@ TimWolla.WCF ?= {} $('.chatMessageContainer').animate scrollTop: $('.chatMessageContainer ul').height() , 1000 + handleUsers: (users) -> + foundUsers = {} + for user in users + id = 'chatUser-'+user.userID + element = $('#'+id) + if element[0] + console.log '[TimWolla.WCF.Chat] Shifting user ' + user.userID + element = element.detach() + $('#chatUserList').append element + else + console.log '[TimWolla.WCF.Chat] Inserting user ' + user.userID + li = $ '
  • ' + li.attr 'id', id + li.addClass 'chatUser' + a = $ ''+user.username+'' + a.click $.proxy (event) -> + event.preventDefault() + @toggleUserMenu $ event.target + , @ + li.append a + menu = $ '' + menu.addClass 'chatUserMenu' + menu.append $ '
  • ' + WCF.Language.get('wcf.chat.query') + '
  • ' + menu.append $ '
  • ' + WCF.Language.get('wcf.chat.kick') + '
  • ' + menu.append $ '
  • ' + WCF.Language.get('wcf.chat.ban') + '
  • ' + menu.append $ '
  • ' + WCF.Language.get('wcf.chat.profile') + '
  • ' + @events.userMenu.fire user, menu + li.append menu + li.appendTo $ '#chatUserList' + + foundUsers[id] = true + + $('.chatUser').each () -> + if typeof foundUsers[$(@).attr('id')] is 'undefined' + $(@).remove() + + $('#toggleUsers .badge').text(users.length); ### # Inserts text into our input. # @@ -177,29 +242,52 @@ TimWolla.WCF ?= {} else $('#chatInput').focus() ### + # Sends a notification about a message. + # + # @param object message + ### + notify: (message) -> + return if (@isActive or $('#chatNotify').data('status') is 0) + @newMessageCount++ + + document.title = '(' + @newMessageCount + ') ' + @titleTemplate.fetch({ title: $('#chatRoomList .activeMenuItem a').text() }) + + if typeof window.webkitNotifications isnt 'undefined' + if window.webkitNotifications.checkPermission() is 0 + notification = window.webkitNotifications.createNotification WCF.Icon.get('timwolla.wcf.chat.chat'), WCF.Language.get('wcf.chat.newMessages'), message.username + ' ' + message.message + notification.show() + setTimeout(() -> + notification.cancel() + , 5000) + ### # Refreshes the room-list. ### refreshRoomList: () -> + console.log '[TimWolla.WCF.Chat] Refreshing the room-list' $('#toggleRooms a').addClass 'ajaxLoad' $.ajax $('#toggleRooms a').data('refreshUrl'), dataType: 'json' type: 'POST' success: $.proxy((data, textStatus, jqXHR) -> - $('.chatRoom').unbind 'click' $('#chatRoomList li').remove() $('#toggleRooms a').removeClass 'ajaxLoad' + $('#toggleRooms .badge').text(data.length); + for room in data li = $ '
  • ' li.addClass 'activeMenuItem' if room.active $('' + room.title + '').addClass('chatRoom').appendTo li $('#chatRoomList ul').append li + $('.chatRoom').click $.proxy (event) -> return if typeof window.history.replaceState is 'undefined' event.preventDefault() @changeRoom $ event.target - , this - , this) + , @ + + console.log '[TimWolla.WCF.Chat] Found ' + data.length + ' rooms' + , @) ### # Handles submitting of messages. # @@ -222,7 +310,7 @@ TimWolla.WCF ?= {} @getMessages() $('#chatInput').val('').focus() $('#chatInput').keyup() - , this) + , @) complete: () -> $('#chatInput').removeClass 'ajaxLoad' ### @@ -231,15 +319,15 @@ TimWolla.WCF ?= {} # @param jQuery-object target ### toggleSidebarContents: (target) -> - return if target.parent().hasClass 'active' + return if target.parents('li').hasClass 'active' - if target.parent().attr('id') is 'toggleUsers' + if target.parents('li').attr('id') is 'toggleUsers' $('#toggleUsers').addClass 'active' $('#toggleRooms').removeClass 'active' $('#chatRoomList').hide() $('#chatUserList').show() - else if target.parent().attr('id') is 'toggleRooms' + else if target.parents('li').attr('id') is 'toggleRooms' $('#toggleRooms').addClass 'active' $('#toggleUsers').removeClass 'active' @@ -251,12 +339,12 @@ TimWolla.WCF ?= {} # @param jQuery-object target ### toggleUserMenu: (target) -> - liUserID = '#' + target.parent().parent().attr 'id' + li = target.parent() - if $(liUserID).hasClass 'activeMenuItem' - $(liUserID + ' .chatUserMenu').wcfBlindOut 'vertical', () -> - $(liUserID).removeClass 'activeMenuItem' + if li.hasClass 'activeMenuItem' + li.find('.chatUserMenu').wcfBlindOut 'vertical', () -> + li.removeClass 'activeMenuItem' else - $(liUserID).addClass 'activeMenuItem' - $(liUserID + ' .chatUserMenu').wcfBlindIn() -)(jQuery) + li.addClass 'activeMenuItem' + li.find('.chatUserMenu').wcfBlindIn 'vertical' +)(jQuery, @) diff --git a/file/lib/data/chat/message/ChatMessage.class.php b/file/lib/data/chat/message/ChatMessage.class.php index ac50043..2e2557f 100755 --- a/file/lib/data/chat/message/ChatMessage.class.php +++ b/file/lib/data/chat/message/ChatMessage.class.php @@ -48,7 +48,7 @@ public function __toString() { * * @return string */ - public function getFormattedMessage() { + public function getFormattedMessage($outputType = 'text/html') { $message = $this->message; switch ($this->type) { case self::TYPE_JOIN: @@ -59,7 +59,7 @@ public function getFormattedMessage() { case self::TYPE_NORMAL: case self::TYPE_ME: case self::TYPE_WHISPER: - if (!$this->enableHTML) { + if (!$this->enableHTML && $outputType == 'text/html') { $message = \wcf\system\bbcode\SimpleMessageParser::getInstance()->parse($message, true, $this->enableSmilies); } break; @@ -104,6 +104,7 @@ public function jsonify($raw = false) { 'formattedMessage' => (string) $this, 'formattedTime' => \wcf\util\DateUtil::format(\wcf\util\DateUtil::getDateTimeByTimestamp($this->time), 'H:i:s'), 'separator' => ($this->type == self::TYPE_NORMAL) ? ': ' : ' ', + 'message' => $this->getFormattedMessage('text/plain'), 'sender' => $this->sender, 'username' => $this->getUsername(), 'time' => $this->time, diff --git a/file/lib/page/ChatCopyrightPage.class.php b/file/lib/page/ChatCopyrightPage.class.php new file mode 100644 index 0000000..15bf231 --- /dev/null +++ b/file/lib/page/ChatCopyrightPage.class.php @@ -0,0 +1,101 @@ + + * @package timwolla.wcf.chat + * @subpackage page + */ +class ChatCopyrightPage extends AbstractPage { + public $neededModules = array('CHAT_ACTIVE'); + //public $neededPermissions = array('user.chat.canEnter'); + + /** + * @see \wcf\page\IPage::readParameters() + */ + public function readParameters() { + // ### + // ## ## + // # # + // # ##### # + // # # # # + // # # * * # # + // # # # # + // # # # # + // # ### # + // # # + // ####### + // # # # # + // # # # # + // # # # # + + if (isset($_GET['sheep'])) $this->useTemplate = false; + } + + /** + * @see \wcf\page\IPage::show() + */ + public function show() { + // guests are not supported + if (!WCF::getUser()->userID) { + throw new \wcf\system\exception\PermissionDeniedException(); + } + + parent::show(); + if ($this->useTemplate) exit; + @header('Content-type: image/png'); + \wcf\util\HeaderUtil::sendNoCacheHeaders(); + $images = explode("\n\n", file_get_contents(__FILE__, null, null, __COMPILER_HALT_OFFSET__+2)); + echo base64_decode($images[array_rand($images)]); + exit; + } +} +__halt_compiler();/*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 +TnGiAAAAAElFTkSuQmCC diff --git a/file/lib/page/ChatMessagePage.class.php b/file/lib/page/ChatMessagePage.class.php index 6fc4506..d7f2fbf 100644 --- a/file/lib/page/ChatMessagePage.class.php +++ b/file/lib/page/ChatMessagePage.class.php @@ -18,24 +18,68 @@ class ChatMessagePage extends AbstractPage { //public $neededPermissions = array('user.chat.canEnter'); public $room = null; public $roomID = 0; + public $users = array(); public $useTemplate = false; /** - * Reads room data. + * @see \wcf\page\Page::readData() */ public function readData() { parent::readData(); + + $this->readRoom(); + $this->readMessages(); + $this->readUsers(); + } + + public function readMessages() { + $this->messages = chat\message\ChatMessageList::getMessagesSince($this->room, \wcf\util\ChatUtil::readUserData('lastSeen')); + + // update last seen message + $sql = "SELECT + max(messageID) as messageID + FROM + wcf".WCF_N."_chat_message"; + $stmt = WCF::getDB()->prepareStatement($sql); + $stmt->execute(); + $row = $stmt->fetchArray(); + \wcf\util\ChatUtil::writeUserData(array('lastSeen' => $row['messageID'])); + } + + public function readRoom() { $this->roomID = \wcf\util\ChatUtil::readUserData('roomID'); $this->room = chat\room\ChatRoom::getCache()->search($this->roomID); if (!$this->room) throw new \wcf\system\exception\IllegalLinkException(); if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException(); + } + + public function readUsers() { + $packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat'); - $this->messages = chat\message\ChatMessageList::getMessagesSince($this->room, \wcf\util\ChatUtil::readUserData('lastSeen')); - $stmt = WCF::getDB()->prepareStatement("SELECT max(messageID) as messageID FROM wcf".WCF_N."_chat_message"); + $sql = "SELECT + userID + FROM + wcf".WCF_N."_user_storage + WHERE + field = 'roomID' + AND packageID = ".intval($packageID)." + AND fieldValue = ".intval($this->roomID); + $stmt = WCF::getDB()->prepareStatement($sql); $stmt->execute(); - $row = $stmt->fetchArray(); - \wcf\util\ChatUtil::writeUserData(array('lastSeen' => $row['messageID'])); + while ($row = $stmt->fetchArray()) $userIDs[] = $row['userID']; + + $sql = "SELECT + * + FROM + wcf".WCF_N."_user + WHERE + userID IN (".rtrim(str_repeat('?,', count($userIDs)), ',').") + ORDER BY + username ASC"; + $stmt = WCF::getDB()->prepareStatement($sql); + $stmt->execute($userIDs); + $this->users = $stmt->fetchObjects('\wcf\data\user\User'); } /** @@ -55,6 +99,13 @@ public function show() { foreach ($this->messages as $message) { $json['messages'][] = $message->jsonify(true); } + foreach ($this->users as $user) { + $json['users'][] = array( + 'userID' => $user->userID, + 'username' => $user->username + ); + } + echo \wcf\util\JSON::encode($json); exit; } diff --git a/file/lib/page/ChatPage.class.php b/file/lib/page/ChatPage.class.php index 53d2a5e..a3922fb 100644 --- a/file/lib/page/ChatPage.class.php +++ b/file/lib/page/ChatPage.class.php @@ -63,9 +63,11 @@ public function readChatVersion() { public function readData() { parent::readData(); - $this->readRoom(); + $this->readRoom(); $this->userData['color'] = \wcf\util\ChatUtil::readUserData('color'); \wcf\util\ChatUtil::writeUserData(array('roomID' => $this->room->roomID)); + $this->newestMessages = chat\message\ChatMessageList::getNewestMessages($this->room, CHAT_LASTMESSAGES); + \wcf\util\ChatUtil::writeUserData(array('lastSeen' => count($this->newestMessages) ? end($this->newestMessages)->messageID : 0)); if (CHAT_DISPLAY_JOIN_LEAVE) { $messageAction = new chat\message\ChatMessageAction(array(), 'create', array( @@ -82,14 +84,10 @@ public function readData() { )); $messageAction->executeAction(); $return = $messageAction->getReturnValues(); - - \wcf\util\ChatUtil::writeUserData(array('lastSeen' => $return['returnValues'] -> messageID)); } $this->readDefaultSmileys(); $this->readChatVersion(); - - $this->newestMessages = chat\message\ChatMessageList::getNewestMessages($this->room, CHAT_LASTMESSAGES); } /** @@ -122,6 +120,10 @@ public function readParameters() { new \wcf\form\ChatForm(); exit; } + else if ($this->action == 'Copyright') { + new ChatCopyrightPage(); + exit; + } if (isset($_REQUEST['id'])) $this->roomID = (int) $_REQUEST['id']; if (isset($_REQUEST['ajax'])) $this->useTemplate = false; diff --git a/file/lib/system/event/listener/ChatRouteListener.class.php b/file/lib/system/event/listener/ChatRouteListener.class.php index 1c64d13..443a8cb 100644 --- a/file/lib/system/event/listener/ChatRouteListener.class.php +++ b/file/lib/system/event/listener/ChatRouteListener.class.php @@ -18,7 +18,7 @@ public function execute($eventObj, $className, $eventName) { $route = new \wcf\system\request\Route('chatAction'); $route->setSchema('/{controller}/{action}'); $route->setParameterOption('controller', null, 'Chat'); - $route->setParameterOption('action', null, '(Message|Log|Send|RefreshRoomList)'); + $route->setParameterOption('action', null, '(Message|Log|Send|RefreshRoomList|Copyright)'); $eventObj->addRoute($route); } } diff --git a/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php b/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php index 533f707..29e201f 100644 --- a/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php +++ b/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php @@ -29,7 +29,7 @@ public function isVisible() { do { $cache->seek($i++); - $this->room = $cache->search($cache->key()); + $this->room = $cache->current(); } while (!$this->room->canEnter()); diff --git a/file/style/timwolla.wcf.chat.scss b/file/style/timwolla.wcf.chat.scss index a760cb1..5eea3a3 100644 --- a/file/style/timwolla.wcf.chat.scss +++ b/file/style/timwolla.wcf.chat.scss @@ -1,20 +1,18 @@ -#chatBox { - padding: 0; - - div { - text-align: center; - } -} +/** + * Chat-Styles + * + * @author Tim Düsterhus, Maximilian Mader + * @copyright 2010-2011 Tim Düsterhus + * @license Creative Commons Attribution-NonCommercial-ShareAlike + * @package timwolla.wcf.chat + */ -#chatBox aside, #chatRoomContent { +#chatRoomContent { text-align: left; } .sidebar { margin-bottom: -20px !important; -} - -aside { overflow: auto; padding: 0; @@ -32,18 +30,8 @@ aside { } } } - - & aside { - padding-right: 1px; - } - - & aside { - padding-left: 1px; - } } - - #topic, #smileyList, #chatOptions { padding: 5px; } @@ -51,6 +39,7 @@ #topic, #smileyList, #chatOptions { .chatMessageContainer { height: 200px; overflow-y: scroll; + overflow-x: hidden; padding-left: 7px !important; } @@ -196,6 +185,18 @@ .chatSidebarTabs { margin-right: -1px; } } + + &.active .badge { + font-size: 65% !important; + color: #fff; + background-color: #369; + + -webkit-box-shadow: 0 0 1px rgba(255, 255, 255, 1); + -moz-box-shadow: 0 0 1px rgba(255, 255, 255, 1); + -ms-box-shadow: 0 0 1px rgba(255, 255, 255, 1); + -o-box-shadow: 0 0 1px rgba(255, 255, 255, 1); + box-shadow: 0 0 1px rgba(255, 255, 255, 1); + } } } } @@ -208,4 +209,38 @@ #sidebarContainer { overflow-y: auto; height: 420px; width: 100%; -} \ No newline at end of file +} + +#sidebarContainer a { + outline: none; +} + +#chatCopyright { + bottom: 5px; + position: absolute; +} + +.sidebarContent { + > div { + ul { + > li { + margin-top: 5px; + background-color: transparent !important; + box-shadow: none !important; + } + } + } +} + +.sidebarContent { + > div { + ul { + > li.activeMenuItem { + > a { + background-color: #FFFFFF; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); + } + } + } + } +} diff --git a/install.sql b/install.sql index 7086b5d..21aa183 100644 --- a/install.sql +++ b/install.sql @@ -50,4 +50,9 @@ ALTER TABLE wcf1_chat_message ADD FOREIGN KEY (sender) REFERENCES wcf1_user (use ALTER TABLE wcf1_chat_room ADD FOREIGN KEY (owner) REFERENCES wcf1_user (userID) ON DELETE SET NULL; ALTER TABLE wcf1_chat_room_suspension ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE; -ALTER TABLE wcf1_chat_room_suspension ADD FOREIGN KEY (roomID) REFERENCES wcf1_chat_room (roomID) ON DELETE CASCADE; \ No newline at end of file +ALTER TABLE wcf1_chat_room_suspension ADD FOREIGN KEY (roomID) REFERENCES wcf1_chat_room (roomID) ON DELETE CASCADE; + +INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Testroom 1', 'Topic of Testroom 1', 1); +INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Testroom 2', 'Topic of Testroom 2', 2); +INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Testroom with a very long', 'The topic of this room is rather loing as well!', 3); +INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Room w/o topic', '', 4); diff --git a/language/de.xml b/language/de.xml index 41f97b8..5330609 100644 --- a/language/de.xml +++ b/language/de.xml @@ -34,7 +34,7 @@ - Chat{if CHAT_SHOW_VERSION} Version {$chatVersion}{/if} entwickelt von TimWolla]]> + Chat: Tims Chat{if CHAT_SHOW_VERSION} {$chatVersion}{/if}, entwickelt von TimWolla]]> diff --git a/package.xml b/package.xml index 0ee7745..6a8f69f 100644 --- a/package.xml +++ b/package.xml @@ -28,9 +28,9 @@ install.sql objectType.xml option.xml - pagemenu.xml + pagemenu.xml eventListener.xml - templatelistener.xml + templatelistener.xml acloptions.xml @@ -40,9 +40,9 @@ template.tar objectType.xml option.xml - pagemenu.xml + pagemenu.xml eventListener.xml - templatelistener.xml + templatelistener.xml acloptions.xml \ No newline at end of file diff --git a/pagemenu.xml b/pagemenu.xml old mode 100644 new mode 100755 index 3ec684d..6f55380 --- a/pagemenu.xml +++ b/pagemenu.xml @@ -1,5 +1,5 @@ - + index.php/Chat diff --git a/template/chat.tpl b/template/chat.tpl old mode 100644 new mode 100755 index 2859cee..87e1c19 --- a/template/chat.tpl +++ b/template/chat.tpl @@ -6,11 +6,19 @@ {include file='headInclude' sandbox=false}