1
0
mirror of https://github.com/wbbaddons/Tims-Chat.git synced 2024-12-22 21:40:08 +00:00

Merge branch 'master' into noJs

This commit is contained in:
Tim Düsterhus 2012-01-14 15:17:11 +01:00
commit c6d97a2161
14 changed files with 315 additions and 92 deletions

View File

@ -1,4 +0,0 @@
language: php
php:
- 5.3
script: php build.php

33
README.md Normal file
View File

@ -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.

86
build.php Normal file → Executable file
View File

@ -1,16 +1,74 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
@unlink('file.tar'); /**
@unlink('template.tar'); * Builds the Chat
@unlink('timwolla.wcf.chat.tar'); *
exec('coffee -cb file/js/*.coffee'); * @author Tim Düsterhus
chdir('file'); * @copyright 2010-2012 Tim Düsterhus
exec('tar cvf ../file.tar * --exclude=*.coffee'); * @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
chdir('..'); * @package timwolla.wcf.chat
chdir('template'); */
exec('tar cvf ../template.tar *'); echo <<<EOT
chdir('..'); Cleaning up
exec('tar cvf timwolla.wcf.chat.tar * --exclude=file --exclude=template --exclude=build.php'); -----------
@unlink('file.tar');
@unlink('template.tar'); EOT;
exec('rm file/js/*.js'); if (file_exists('file.tar')) unlink('file.tar');
if (file_exists('template.tar')) unlink('template.tar');
foreach (glob('file/js/*.js') as $jsFile) unlink($jsFile);
foreach (glob('file/style/*.css') as $cssFile) unlink($cssFile);
if (file_exists('timwolla.wcf.chat.tar')) unlink('timwolla.wcf.chat.tar');
echo <<<EOT
Building JavaScript
-------------------
EOT;
foreach (glob('file/js/*.coffee') as $coffeeFile) {
echo $coffeeFile."\n";
passthru('coffee -cb '.escapeshellarg($coffeeFile), $code);
if ($code != 0) exit($code);
}
echo <<<EOT
Building CSS
------------
EOT;
foreach (glob('file/style/*.scss') as $sassFile) {
echo $sassFile."\n";
passthru('scss '.escapeshellarg($sassFile).' '.escapeshellarg(substr($sassFile, 0, -4).'css'), $code);
if ($code != 0) exit($code);
}
echo <<<EOT
Building file.tar
-----------------
EOT;
chdir('file');
passthru('tar cvf ../file.tar * --exclude=*.coffee --exclude=*.scss', $code);
if ($code != 0) exit($code);
echo <<<EOT
Building template.tar
---------------------
EOT;
chdir('../template');
passthru('tar cvf ../template.tar *', $code);
if ($code != 0) exit($code);
echo <<<EOT
Building timwolla.wcf.chat.tar
------------------------------
EOT;
chdir('..');
passthru('tar cvf timwolla.wcf.chat.tar * --exclude=file --exclude=template --exclude=build.php', $code);
if ($code != 0) exit($code);
if (file_exists('file.tar')) unlink('file.tar');
if (file_exists('template.tar')) unlink('template.tar');
foreach (glob('file/js/*.js') as $jsFile) unlink($jsFile);
foreach (glob('file/style/*.css') as $cssFile) unlink($cssFile);

View File

@ -13,18 +13,39 @@ TimWolla.WCF ?= {}
(($) -> (($) ->
TimWolla.WCF.Chat = TimWolla.WCF.Chat =
titleTemplate: null titleTemplate: null
title: document.title
messageTemplate: null messageTemplate: null
newMessageCount: null
events:
newMessage: $.Callbacks()
userMenu: $.Callbacks()
init: () -> init: () ->
console.log('[TimWolla.WCF.Chat] Initializing');
@bindEvents() @bindEvents()
@refreshRoomList() @refreshRoomList()
new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, this), 60e3 new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, this), 60e3
new WCF.PeriodicalExecuter $.proxy(@getMessages, this), @config.reloadTime * 1000 new WCF.PeriodicalExecuter $.proxy(@getMessages, this), @config.reloadTime * 1000
@getMessages()
$('#chatInput').focus() $('#chatInput').focus()
console.log '[TimWolla.WCF.Chat] Finished initializing'
### ###
# Binds all the events needed for Tims Chat. # Binds all the events needed for Tims Chat.
### ###
bindEvents: () -> bindEvents: () ->
@isActive = true
$(window).focus $.proxy () ->
document.title = @title
@newMessageCount = 0
clearTimeout @timeout
@isActive = true
, this
$(window).blur $.proxy () ->
@title = document.title
@isActive = false
, this
$('.smiley').click $.proxy (event) -> $('.smiley').click $.proxy (event) ->
@insertText ' ' + $(event.target).attr('alt') + ' ' @insertText ' ' + $(event.target).attr('alt') + ' '
, this , this
@ -34,11 +55,6 @@ TimWolla.WCF ?= {}
@toggleSidebarContents $ event.target @toggleSidebarContents $ event.target
, this , this
$('.chatUser .chatUserLink').click $.proxy (event) ->
event.preventDefault()
@toggleUserMenu $ event.target
, this
$('#chatForm').submit $.proxy (event) -> $('#chatForm').submit $.proxy (event) ->
event.preventDefault() event.preventDefault()
@submit $ event.target @submit $ event.target
@ -108,6 +124,7 @@ TimWolla.WCF ?= {}
### ###
freeTheFish: () -> freeTheFish: () ->
return if $.wcfIsset('fish') return if $.wcfIsset('fish')
console.warn '[TimWolla.WCF.Chat] Freeing the fish'
fish = $ '<div id="fish">' + WCF.String.escapeHTML('><((((°>') + '</div>' fish = $ '<div id="fish">' + WCF.String.escapeHTML('><((((°>') + '</div>'
fish.css fish.css
position: 'absolute' position: 'absolute'
@ -120,15 +137,20 @@ TimWolla.WCF ?= {}
fish.appendTo $ 'body' fish.appendTo $ 'body'
new WCF.PeriodicalExecuter(() -> new WCF.PeriodicalExecuter(() ->
left = (Math.random() * 100 - 50) left = (Math.random() * 100 - 50)
top = (Math.random() * 100 - 50)
fish = $('#fish')
$('#fish').text('><((((°>') if (left > 0) left *= -1 if((fish.position().left + left) < (0 + fish.width()) or (fish.position().left + left) > ($(document).width() - fish.width()))
$('#fish').text('<°))))><') if (left < 0) top *= -1 if((fish.position().top + top) < (0 + fish.height()) or (fish.position().top + top) > ($(document).height() - fish.height()))
$('#fish').animate fish.text('><((((°>') if (left > 0)
top: '+=' + (Math.random() * 100 - 50) fish.text('<°))))><') if (left < 0)
fish.animate
top: '+=' + top
left: '+=' + left left: '+=' + left
, 1000 , 1000
, 3e3); , 1.5e3);
### ###
# Loads new messages. # Loads new messages.
### ###
@ -137,7 +159,17 @@ TimWolla.WCF ?= {}
dataType: 'json' dataType: 'json'
type: 'POST' type: 'POST'
success: $.proxy((data, textStatus, jqXHR) -> success: $.proxy((data, textStatus, jqXHR) ->
@handleMessages(data) if (!@isActive && $('#chatNotify').data('status') is 1)
@newMessageCount += data.messages.length
if (@newMessageCount > 0)
@timeout = setTimeout $.proxy(() ->
document.title = @newMessageCount + WCF.Language.get('wcf.chat.newMessages')
setTimeout $.proxy(() ->
document.title = @title
, this), 3000
, this), 1000
@handleMessages(data.messages)
@handleUsers(data.users)
, this) , this)
### ###
# Inserts the new messages. # Inserts the new messages.
@ -146,6 +178,8 @@ TimWolla.WCF ?= {}
### ###
handleMessages: (messages) -> handleMessages: (messages) ->
for message in messages for message in messages
@events.newMessage.fire message
output = @messageTemplate.fetch message output = @messageTemplate.fetch message
li = $ '<li></li>' li = $ '<li></li>'
li.addClass 'chatMessage chatMessage'+message.type li.addClass 'chatMessage chatMessage'+message.type
@ -156,6 +190,43 @@ TimWolla.WCF ?= {}
$('.chatMessageContainer').animate $('.chatMessageContainer').animate
scrollTop: $('.chatMessageContainer ul').height() scrollTop: $('.chatMessageContainer ul').height()
, 1000 , 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></li>'
li.attr 'id', id
li.addClass 'chatUser'
a = $ '<a href="javascript:;">'+user.username+'</a>'
a.click $.proxy (event) ->
event.preventDefault()
@toggleUserMenu $ event.target
, this
li.append a
menu = $ '<ul></ul>'
menu.addClass 'chatUserMenu'
menu.append $ '<li><a href="javascript:;">{lang}wcf.chat.query{/lang}</a></li>'
menu.append $ '<li><a href="javascript:;">{lang}wcf.chat.kick{/lang}</a></li>'
menu.append $ '<li><a href="javascript:;">{lang}wcf.chat.ban{/lang}</a></li>'
menu.append $ '<li><a href="index.php/User/'+user.userID+'">{lang}wcf.chat.profile{/lang}</a></li>'
@events.userMenu.fire user, menu
li.append menu
li.appendTo $ '#chatUserList'
foundUsers[id] = true
$('.chatUser').each () ->
if typeof foundUsers[$(this).attr('id')] is 'undefined'
$(this).remove()
$('#toggleUsers .badge').text(users.length);
### ###
# Inserts text into our input. # Inserts text into our input.
# #
@ -180,25 +251,30 @@ TimWolla.WCF ?= {}
# Refreshes the room-list. # Refreshes the room-list.
### ###
refreshRoomList: () -> refreshRoomList: () ->
console.log '[TimWolla.WCF.Chat] Refreshing the room-list'
$('#toggleRooms a').addClass 'ajaxLoad' $('#toggleRooms a').addClass 'ajaxLoad'
$.ajax $('#toggleRooms a').data('refreshUrl'), $.ajax $('#toggleRooms a').data('refreshUrl'),
dataType: 'json' dataType: 'json'
type: 'POST' type: 'POST'
success: $.proxy((data, textStatus, jqXHR) -> success: $.proxy((data, textStatus, jqXHR) ->
$('.chatRoom').unbind 'click'
$('#chatRoomList li').remove() $('#chatRoomList li').remove()
$('#toggleRooms a').removeClass 'ajaxLoad' $('#toggleRooms a').removeClass 'ajaxLoad'
$('#toggleRooms .badge').text(data.length);
for room in data for room in data
li = $ '<li></li>' li = $ '<li></li>'
li.addClass 'activeMenuItem' if room.active li.addClass 'activeMenuItem' if room.active
$('<a href="' + room.link + '">' + room.title + '</a>').addClass('chatRoom').appendTo li $('<a href="' + room.link + '">' + room.title + '</a>').addClass('chatRoom').appendTo li
$('#chatRoomList ul').append li $('#chatRoomList ul').append li
$('.chatRoom').click $.proxy (event) -> $('.chatRoom').click $.proxy (event) ->
return if typeof window.history.replaceState is 'undefined' return if typeof window.history.replaceState is 'undefined'
event.preventDefault() event.preventDefault()
@changeRoom $ event.target @changeRoom $ event.target
, this , this
console.log '[TimWolla.WCF.Chat] Found ' + data.length + ' rooms'
, this) , this)
### ###
# Handles submitting of messages. # Handles submitting of messages.
@ -251,12 +327,12 @@ TimWolla.WCF ?= {}
# @param jQuery-object target # @param jQuery-object target
### ###
toggleUserMenu: (target) -> toggleUserMenu: (target) ->
liUserID = '#' + target.parent().parent().attr 'id' li = target.parent()
if $(liUserID).hasClass 'activeMenuItem' if li.hasClass 'activeMenuItem'
$(liUserID + ' .chatUserMenu').wcfBlindOut 'vertical', () -> li.find('.chatUserMenu').wcfBlindOut 'vertical', () ->
$(liUserID).removeClass 'activeMenuItem' li.removeClass 'activeMenuItem'
else else
$(liUserID).addClass 'activeMenuItem' li.addClass 'activeMenuItem'
$(liUserID + ' .chatUserMenu').wcfBlindIn() li.find('.chatUserMenu').wcfBlindIn 'vertical'
)(jQuery) )(jQuery)

View File

@ -36,9 +36,7 @@ class ChatMessage extends \wcf\data\DatabaseObject {
const TYPE_GLOBALMESSAGE = 11; const TYPE_GLOBALMESSAGE = 11;
/** /**
* Returns the message. * @see \wcf\data\chat\message\ChatMessage::getFormattedMessage()
*
* @return string
*/ */
public function __toString() { public function __toString() {
return $this->getFormattedMessage(); return $this->getFormattedMessage();
@ -91,10 +89,11 @@ public function getUsername() {
/** /**
* Converts this message into json-form. * Converts this message into json-form.
* *
* @param boolean $raw
* @return string * @return string
*/ */
public function jsonify() { public function jsonify($raw = false) {
return \wcf\util\JSON::encode(array( $array = array(
'formattedUsername' => $this->getFormattedUsername(), 'formattedUsername' => $this->getFormattedUsername(),
'formattedMessage' => (string) $this, 'formattedMessage' => (string) $this,
'formattedTime' => \wcf\util\DateUtil::format(\wcf\util\DateUtil::getDateTimeByTimestamp($this->time), 'H:i:s'), 'formattedTime' => \wcf\util\DateUtil::format(\wcf\util\DateUtil::getDateTimeByTimestamp($this->time), 'H:i:s'),
@ -104,6 +103,9 @@ public function jsonify() {
'receiver' => $this->receiver, 'receiver' => $this->receiver,
'type' => $this->type, 'type' => $this->type,
'roomID' => $this->roomID 'roomID' => $this->roomID
)); );
if ($raw) return $array;
return \wcf\util\JSON::encode($array);
} }
} }

View File

@ -18,24 +18,68 @@ class ChatMessagePage extends AbstractPage {
//public $neededPermissions = array('user.chat.canEnter'); //public $neededPermissions = array('user.chat.canEnter');
public $room = null; public $room = null;
public $roomID = 0; public $roomID = 0;
public $users = array();
public $useTemplate = false; public $useTemplate = false;
/** /**
* Reads room data. * @see \wcf\page\Page::readData()
*/ */
public function readData() { public function readData() {
parent::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->roomID = \wcf\util\ChatUtil::readUserData('roomID');
$this->room = chat\room\ChatRoom::getCache()->search($this->roomID); $this->room = chat\room\ChatRoom::getCache()->search($this->roomID);
if (!$this->room) throw new \wcf\system\exception\IllegalLinkException(); if (!$this->room) throw new \wcf\system\exception\IllegalLinkException();
if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException(); 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')); $sql = "SELECT
$stmt = WCF::getDB()->prepareStatement("SELECT max(messageID) as messageID FROM wcf".WCF_N."_chat_message"); 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(); $stmt->execute();
$row = $stmt->fetchArray(); while ($row = $stmt->fetchArray()) $userIDs[] = $row['userID'];
\wcf\util\ChatUtil::writeUserData(array('lastSeen' => $row['messageID']));
$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');
} }
/** /**
@ -50,11 +94,19 @@ public function show() {
parent::show(); parent::show();
@header('Content-type: application/json'); @header('Content-type: application/json');
$result = '['; $json = array('users' => array(), 'messages' => array());
foreach ($this->messages as $message) { foreach ($this->messages as $message) {
$result .= $message->jsonify().','; $json['messages'][] = $message->jsonify(true);
} }
echo rtrim($result, ',').']'; foreach ($this->users as $user) {
$json['users'][] = array(
'userID' => $user->userID,
'username' => $user->username
);
}
echo \wcf\util\JSON::encode($json);
exit; exit;
} }
} }

View File

@ -66,6 +66,8 @@ public function readData() {
$this->readRoom(); $this->readRoom();
$this->userData['color'] = \wcf\util\ChatUtil::readUserData('color'); $this->userData['color'] = \wcf\util\ChatUtil::readUserData('color');
\wcf\util\ChatUtil::writeUserData(array('roomID' => $this->room->roomID)); \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' => end($this->newestMessages)->messageID));
if (CHAT_DISPLAY_JOIN_LEAVE) { if (CHAT_DISPLAY_JOIN_LEAVE) {
$messageAction = new chat\message\ChatMessageAction(array(), 'create', array( $messageAction = new chat\message\ChatMessageAction(array(), 'create', array(
@ -82,14 +84,10 @@ public function readData() {
)); ));
$messageAction->executeAction(); $messageAction->executeAction();
$return = $messageAction->getReturnValues(); $return = $messageAction->getReturnValues();
\wcf\util\ChatUtil::writeUserData(array('lastSeen' => $return['returnValues'] -> messageID));
} }
$this->readDefaultSmileys(); $this->readDefaultSmileys();
$this->readChatVersion(); $this->readChatVersion();
$this->newestMessages = chat\message\ChatMessageList::getNewestMessages($this->room, CHAT_LASTMESSAGES);
} }
/** /**

View File

@ -29,7 +29,7 @@ public function isVisible() {
do { do {
$cache->seek($i++); $cache->seek($i++);
$this->room = $cache->search($cache->key()); $this->room = $cache->current();
} }
while (!$this->room->canEnter()); while (!$this->room->canEnter());

View File

@ -1,20 +1,18 @@
#chatBox { /**
padding: 0; * Chat-Styles
*
div { * @author Tim Düsterhus, Maximilian Mader
text-align: center; * @copyright 2010-2011 Tim Düsterhus
} * @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
} * @package timwolla.wcf.chat
*/
#chatBox aside, #chatRoomContent { #chatRoomContent {
text-align: left; text-align: left;
} }
.sidebar { .sidebar {
margin-bottom: -20px !important; margin-bottom: -20px !important;
}
aside {
overflow: auto; overflow: auto;
padding: 0; padding: 0;
@ -32,18 +30,8 @@ aside {
} }
} }
} }
& aside {
padding-right: 1px;
}
& aside {
padding-left: 1px;
}
} }
#topic, #smileyList, #chatOptions { #topic, #smileyList, #chatOptions {
padding: 5px; padding: 5px;
} }
@ -51,6 +39,7 @@ #topic, #smileyList, #chatOptions {
.chatMessageContainer { .chatMessageContainer {
height: 200px; height: 200px;
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden;
padding-left: 7px !important; padding-left: 7px !important;
} }
@ -196,6 +185,18 @@ .chatSidebarTabs {
margin-right: -1px; 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);
}
} }
} }
} }

View File

@ -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 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 (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; 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);

View File

@ -28,9 +28,9 @@
<instruction type="sql">install.sql</instruction> <instruction type="sql">install.sql</instruction>
<instruction type="objectType">objectType.xml</instruction> <instruction type="objectType">objectType.xml</instruction>
<instruction type="option">option.xml</instruction> <instruction type="option">option.xml</instruction>
<instruction type="pagemenu">pagemenu.xml</instruction> <instruction type="pageMenu">pagemenu.xml</instruction>
<instruction type="eventListener">eventListener.xml</instruction> <instruction type="eventListener">eventListener.xml</instruction>
<instruction type="templatelistener">templatelistener.xml</instruction> <instruction type="templateListener">templatelistener.xml</instruction>
<instruction type="aclOption">acloptions.xml</instruction> <instruction type="aclOption">acloptions.xml</instruction>
</instructions> </instructions>
@ -40,9 +40,9 @@
<instruction type="template">template.tar</instruction> <instruction type="template">template.tar</instruction>
<instruction type="objectType">objectType.xml</instruction> <instruction type="objectType">objectType.xml</instruction>
<instruction type="option">option.xml</instruction> <instruction type="option">option.xml</instruction>
<instruction type="pagemenu">pagemenu.xml</instruction> <instruction type="pageMenu">pagemenu.xml</instruction>
<instruction type="eventListener">eventListener.xml</instruction> <instruction type="eventListener">eventListener.xml</instruction>
<instruction type="templatelistener">templatelistener.xml</instruction> <instruction type="templateListener">templatelistener.xml</instruction>
<instruction type="aclOption">acloptions.xml</instruction> <instruction type="aclOption">acloptions.xml</instruction>
</instructions> </instructions>
</package> </package>

2
pagemenu.xml Normal file → Executable file
View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/pagemnu.xsd"> <data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/pagemenu.xsd">
<import> <import>
<pagemenuitem name="wcf.header.menu.chat"> <pagemenuitem name="wcf.header.menu.chat">
<link>index.php/Chat</link> <link>index.php/Chat</link>

View File

@ -76,19 +76,19 @@
<body id="tpl{$templateName|ucfirst}"> <body id="tpl{$templateName|ucfirst}">
{capture assign='sidebar'} {capture assign='sidebar'}
<div id="sidebarMenu"> <div id="sidebarContent">
<nav class="chatSidebarTabs"> <nav class="chatSidebarTabs">
<ul> <ul>
<li id="toggleUsers" class="active"><a href="javascript:;" title="{lang}wcf.chat.users{/lang}">{lang}wcf.chat.users{/lang}</a></li> <li id="toggleUsers" class="active"><a href="javascript:;" title="{lang}wcf.chat.users{/lang}">{lang}wcf.chat.users{/lang} <span class="badge">0</span></a></li>
<li id="toggleRooms"><a href="javascript:;" title="{lang}wcf.chat.rooms{/lang}" data-refresh-url="{link controller="Chat" action="RefreshRoomList"}{/link}">{lang}wcf.chat.rooms{/lang}</a></li> <li id="toggleRooms"><a href="javascript:;" title="{lang}wcf.chat.rooms{/lang}" data-refresh-url="{link controller="Chat" action="RefreshRoomList"}{/link}">{lang}wcf.chat.rooms{/lang} <span class="badge">{#$rooms|count}</span></a></li>
</ul> </ul>
</nav> </nav>
<div id="sidebarContainer"> <div id="sidebarContainer">
<ul id="chatUserList"> <ul id="chatUserList">
{section name=user start=1 loop=26} {*section name=user start=1 loop=26}
<li id="user-{$user}" class="chatUser"> <li class="chatUser">
<span class="bgFix"><a class="chatUserLink" href="javascript:;">User {$user}</a></span> <a href="javascript:;">User {$user}</a>
<ul class="chatUserMenu"> <ul class="chatUserMenu">
<li> <li>
<a href="javascript:;">{lang}wcf.chat.query{/lang}</a> <a href="javascript:;">{lang}wcf.chat.query{/lang}</a>
@ -98,7 +98,7 @@
</li> </li>
</ul> </ul>
</li> </li>
{/section} {/section*}
</ul> </ul>
<nav id="chatRoomList" class="sidebarMenu" style="display: none;"> <nav id="chatRoomList" class="sidebarMenu" style="display: none;">
<div> <div>
@ -116,7 +116,7 @@
</div> </div>
</div> </div>
{/capture} {/capture}
{include file='header' sandbox=false sidebarDirection='right'} {include file='header' sandbox=false sidebarOrientation='right'}
<div id="chatRoomContent"> <div id="chatRoomContent">
<div id="topic" class="border"{if $room->topic|language === ''} style="display: none;"{/if}>{$room->topic|language}</div> <div id="topic" class="border"{if $room->topic|language === ''} style="display: none;"{/if}>{$room->topic|language}</div>
@ -167,7 +167,7 @@
<a id="chatMark" href="javascript:;" class="balloonTooltip" title="Show checkboxes"> <a id="chatMark" href="javascript:;" class="balloonTooltip" title="Show checkboxes">
<img alt="" src="{icon}check1{/icon}" /> <span>{lang}wcf.chat.mark{/lang}</span> <img alt="" src="{icon}check1{/icon}" /> <span>{lang}wcf.chat.mark{/lang}</span>
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
@ -184,7 +184,9 @@
animations: {CHAT_ANIMATIONS}, animations: {CHAT_ANIMATIONS},
maxTextLength: {CHAT_LENGTH} maxTextLength: {CHAT_LENGTH}
} }
{event name='shouldInit'}
TimWolla.WCF.Chat.init(); TimWolla.WCF.Chat.init();
{event name='didInit'}
TimWolla.WCF.Chat.handleMessages([ TimWolla.WCF.Chat.handleMessages([
{implode from=$newestMessages item='message'} {implode from=$newestMessages item='message'}
{@$message->jsonify()} {@$message->jsonify()}

View File

@ -1 +1 @@
{literal}<time>{@$formattedTime}</time> {@$formattedUsername} {@$formattedMessage}{/literal} {literal}<dl style="margin: 0;"><dt style="width: 145px; margin: 0;"><time style="float: left;">{@$formattedTime}</time> {@$formattedUsername}</dt> <dd style="padding: 0; margin-left: 150px;">{@$formattedMessage}</dd></dl>{/literal}