mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2025-01-22 02:00:40 +00:00
Merge branch 'master' into commands
Conflicts: file/lib/form/ChatForm.class.php template/chatMessage.tpl
This commit is contained in:
commit
81bdbccbe2
@ -1,8 +1,34 @@
|
||||
<?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/maelstrom/aclOption.xsd">
|
||||
<import>
|
||||
<option name="canEnter">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
</option>
|
||||
<categories>
|
||||
<category name="user">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
</category>
|
||||
<category name="mod">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
</category>
|
||||
</categories>
|
||||
|
||||
<options>
|
||||
<option name="user.canEnter">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
<categoryname>user</categoryname>
|
||||
</option>
|
||||
<option name="user.canWrite">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
<categoryname>user</categoryname>
|
||||
</option>
|
||||
|
||||
|
||||
<option name="mod.canAlwaysEnter">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
<categoryname>mod</categoryname>
|
||||
</option>
|
||||
<option name="mod.canAlwaysWrite">
|
||||
<objecttype>timwolla.wcf.chat.room</objecttype>
|
||||
<categoryname>mod</categoryname>
|
||||
</option>
|
||||
</options>
|
||||
</import>
|
||||
</data>
|
22
acpMenu.xml
Normal file
22
acpMenu.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?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/maelstrom/acpMenu.xsd">
|
||||
<import>
|
||||
<acpmenuitem name="wcf.acp.menu.link.chat">
|
||||
<parent>wcf.acp.menu.link.content</parent>
|
||||
</acpmenuitem>
|
||||
|
||||
<acpmenuitem name="wcf.acp.menu.link.chat.room.list">
|
||||
<link>index.php/ChatRoomList/</link>
|
||||
<parent>wcf.acp.menu.link.chat</parent>
|
||||
<permissions>admin.content.chat.canEditRoom,admin.content.chat.canDeleteRoom</permissions>
|
||||
<showorder>1</showorder>
|
||||
</acpmenuitem>
|
||||
|
||||
<acpmenuitem name="wcf.acp.menu.link.chat.room.add">
|
||||
<link>index.php/ChatRoomAdd/</link>
|
||||
<parent>wcf.acp.menu.link.chat</parent>
|
||||
<permissions>admin.content.chat.canAddRoom</permissions>
|
||||
<showorder>2</showorder>
|
||||
</acpmenuitem>
|
||||
</import>
|
||||
</data>
|
101
acptemplate/chatRoomAdd.tpl
Normal file
101
acptemplate/chatRoomAdd.tpl
Normal file
@ -0,0 +1,101 @@
|
||||
{include file='header'}
|
||||
|
||||
<!-- ToDo: DEBUG ONLY -->
|
||||
<link rel="stylesheet" type="text/css" href="{@$__wcf->getPath('wcf')}style/acl.css" />
|
||||
<!-- /DEBUG ONLY -->
|
||||
|
||||
<script type="text/javascript" src="{@$__wcf->getPath('wcf')}js/WCF.ACL.js"></script>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
$(function() {
|
||||
WCF.Icon.addObject({
|
||||
'wcf.icon.delete': '{@$__wcf->getPath('wcf')}icon/delete1.svg',
|
||||
'wcf.icon.user': '{@$__wcf->getPath('wcf')}icon/user1.svg',
|
||||
'wcf.icon.users': '{@$__wcf->getPath('wcf')}icon/users1.svg'
|
||||
});
|
||||
|
||||
new WCF.ACL.List($('#groupPermissions'), {@$objectTypeID}, ''{if $roomID|isset}, {@$roomID}{/if});
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<header class="wcf-mainHeading wcf-container">
|
||||
<img src="{@$__wcf->getPath('wcf')}icon/{$action}1.svg" alt="" class="wcf-containerIcon" />
|
||||
<hgroup class="wcf-containerContent">
|
||||
<h1>{lang}wcf.acp.chat.room.{$action}{/lang}</h1>
|
||||
</hgroup>
|
||||
</header>
|
||||
|
||||
{if $errorField}
|
||||
<p class="wcf-error">{lang}wcf.global.form.error{/lang}</p>
|
||||
{/if}
|
||||
|
||||
{if $success|isset}
|
||||
<p class="wcf-success">{lang}wcf.global.form.{$action}.success{/lang}</p>
|
||||
{/if}
|
||||
|
||||
<div class="wcf-contentHeader">
|
||||
<nav>
|
||||
<ul class="wcf-largeButtons">
|
||||
<li><a href="{link controller='ChatRoomList'}{/link}" title="{lang}wcf.acp.menu.link.chat.room.list{/lang}" class="wcf-button"><img src="{@$__wcf->getPath('wcf')}icon/chat1.svg" alt="" /> <span>{lang}wcf.acp.menu.link.chat.room.list{/lang}</span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<form method="post" action="{if $action == 'add'}{link controller='ChatRoomAdd'}{/link}{else}{link controller='ChatRoomEdit'}{/link}{/if}">
|
||||
<div class="wcf-border wcf-content">
|
||||
<fieldset>
|
||||
<legend>{lang}wcf.acp.chat.room.data{/lang}</legend>
|
||||
|
||||
<dl{if $errorField == 'title'} class="wcf-formError"{/if}>
|
||||
<dt><label for="title">{lang}wcf.acp.chat.room.title{/lang}</label></dt>
|
||||
<dd>
|
||||
<input type="text" id="title" name="title" value="{$title}" autofocus="autofocus" class="long" />
|
||||
{if $errorField == 'title'}
|
||||
<small class="wcf-innerError">
|
||||
{if $errorType == 'empty'}
|
||||
{lang}wcf.global.form.error.empty{/lang}
|
||||
{else}
|
||||
{lang}wcf.acp.chat.room.title.error.{@$errorType}{/lang}
|
||||
{/if}
|
||||
</small>
|
||||
{/if}
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
{include file='multipleLanguageInputJavascript' elementIdentifier='title'}
|
||||
|
||||
<dl{if $errorField == 'topic'} class="wcf-formError"{/if}>
|
||||
<dt><label for="topic">{lang}wcf.acp.chat.room.topic{/lang}</label></dt>
|
||||
<dd>
|
||||
<input type="text" id="topic" name="topic" value="{$topic}" class="long" />
|
||||
{if $errorField == 'topic'}
|
||||
<small class="wcf-innerError">
|
||||
{if $errorType == 'empty'}
|
||||
{lang}wcf.global.form.error.empty{/lang}
|
||||
{else}
|
||||
{lang}wcf.acp.chat.room.topic.error.{@$errorType}{/lang}
|
||||
{/if}
|
||||
</small>
|
||||
{/if}
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
{include file='multipleLanguageInputJavascript' elementIdentifier='topic'}
|
||||
|
||||
<dl id="groupPermissions">
|
||||
<dt>{lang}wcf.acp.acl.permissions{/lang}</dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="wcf-formSubmit">
|
||||
<input type="reset" value="{lang}wcf.global.button.reset{/lang}" accesskey="r" />
|
||||
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
|
||||
{@SID_INPUT_TAG}
|
||||
{if $roomID|isset}<input type="hidden" name="id" value="{@$roomID}" />{/if}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{include file='footer'}
|
58
acptemplate/chatRoomList.tpl
Normal file
58
acptemplate/chatRoomList.tpl
Normal file
@ -0,0 +1,58 @@
|
||||
{include file='header'}
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
$(function() {
|
||||
new WCF.Action.Delete('\\wcf\\data\\chat\\room\\ChatRoomAction', $('.chatRoomRow'));
|
||||
new WCF.Sortable.List('chatRoomList', '\\wcf\\data\\chat\\room\\ChatRoomAction');
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<header class="wcf-mainHeading wcf-container">
|
||||
<img src="{@$__wcf->getPath('wcf')}icon/chat1.svg" alt="" class="wcf-containerIcon" />
|
||||
<hgroup class="wcf-containerContent">
|
||||
<h1>{lang}wcf.acp.chat.room.list{/lang}</h1>
|
||||
</hgroup>
|
||||
</header>
|
||||
|
||||
<div class="wcf-contentHeader">
|
||||
{pages print=true assign=pagesLinks controller="ChatRoomList" link="pageNo=%d"}
|
||||
|
||||
{if $__wcf->session->getPermission('admin.content.chat.canAddRoom')}
|
||||
<nav>
|
||||
<ul class="wcf-largeButtons">
|
||||
<li><a href="{link controller='ChatRoomAdd'}{/link}" title="{lang}wcf.acp.chat.room.add{/lang}" class="wcf-button"><img src="{@$__wcf->getPath('wcf')}icon/add1.svg" alt="" /> <span>{lang}wcf.acp.chat.room.add{/lang}</span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<section id="chatRoomList" class="wcf-border wcf-sortableListContainer">
|
||||
{hascontent}
|
||||
<ol class="wcf-sortableList" data-object-id="0">
|
||||
{content}
|
||||
{foreach from=$objects item=chatRoom}
|
||||
<li class="wcf-sortableNode chatRoomRow" data-object-id="{@$chatRoom->roomID}">
|
||||
<span class="wcf-sortableNodeLabel">
|
||||
<a href="{link controller='ChatRoomEdit' id=$chatRoom->roomID}{/link}">{$chatRoom->title|language}</a>
|
||||
|
||||
<span class="wcf-sortableButtonContainer">
|
||||
{if $__wcf->session->getPermission('admin.content.chat.canEditRoom')}
|
||||
<a href="{link controller='ChatRoomEdit' id=$chatRoom->roomID}{/link}"><img src="{@$__wcf->getPath('wcf')}icon/edit1.svg" alt="" title="{lang}wcf.global.button.edit{/lang}" class="balloonTooltip" /></a>
|
||||
{/if}
|
||||
{if $__wcf->session->getPermission('admin.content.chat.canDeleteRoom')}
|
||||
<img src="{@$__wcf->getPath('wcf')}icon/delete1.svg" alt="" title="{lang}wcf.global.button.delete{/lang}" class="jsDeleteButton jsTooltip" data-object-id="{@$chatRoom->roomID}" data-confirm-message="{lang}wcf.acp.bbcode.delete.sure{/lang}" />
|
||||
{/if}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
{/foreach}
|
||||
{/content}
|
||||
</ol>
|
||||
{hascontentelse}
|
||||
<p class="wcf-warning">{lang}wcf.acp.chat.room.noneAvailable{/lang}</p>
|
||||
{/hascontent}
|
||||
</section>
|
||||
|
||||
{include file='footer'}
|
13
build.php
13
build.php
@ -15,6 +15,7 @@ Cleaning up
|
||||
EOT;
|
||||
if (file_exists('file.tar')) unlink('file.tar');
|
||||
if (file_exists('template.tar')) unlink('template.tar');
|
||||
if (file_exists('acptemplate.tar')) unlink('acptemplate.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');
|
||||
@ -60,15 +61,25 @@ EOT;
|
||||
if ($code != 0) exit($code);
|
||||
echo <<<EOT
|
||||
|
||||
Building acptemplate.tar
|
||||
---------------------
|
||||
|
||||
EOT;
|
||||
chdir('../acptemplate');
|
||||
passthru('tar cvf ../acptemplate.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);
|
||||
passthru('tar cvf timwolla.wcf.chat.tar * --exclude=file --exclude=template --exclude=acptemplate --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');
|
||||
if (file_exists('acptemplate.tar')) unlink('acptemplate.tar');
|
||||
foreach (glob('file/js/*.js') as $jsFile) unlink($jsFile);
|
||||
foreach (glob('file/style/*.css') as $cssFile) unlink($cssFile);
|
||||
|
34
file/acp/timwolla.wcf.chat.update.php
Normal file
34
file/acp/timwolla.wcf.chat.update.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace timwolla\wcf\chat;
|
||||
|
||||
/**
|
||||
* Handles updates.
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
*/
|
||||
final class Update {
|
||||
private $rooms = null;
|
||||
public function __construct() {
|
||||
$this->rooms = \wcf\data\chat\room\ChatRoom::getCache();
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
foreach ($this->rooms as $room) {
|
||||
$messageAction = new \wcf\data\chat\message\ChatMessageAction(array(), 'create', array(
|
||||
'data' => array(
|
||||
'roomID' => $room->roomID,
|
||||
'time' => TIME_NOW,
|
||||
'type' => \wcf\data\chat\message\ChatMessage::TYPE_INFORMATION,
|
||||
// TODO: Language item
|
||||
'message' => 'Tims Chat was updated. Please refresh the page.'
|
||||
)
|
||||
));
|
||||
$messageAction->executeAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
$update = new Update();
|
||||
$update->execute();
|
58
file/icon/chat.svg
Normal file
58
file/icon/chat.svg
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!--
|
||||
@author Maximilian Mader
|
||||
@copyright 2011 Tim Düsterhus
|
||||
@license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
-->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" xml:space="preserve">
|
||||
<title>Chat</title>
|
||||
<desc>Chat Icon (outlined)</desc>
|
||||
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.Lower .bubble {
|
||||
fill:none;
|
||||
stroke:#ffffff;
|
||||
stroke-opacity:1;
|
||||
}
|
||||
.Lower .leaderLine {
|
||||
fill:#ffffff;
|
||||
fill-opacity:1;
|
||||
stroke:none;
|
||||
}
|
||||
.Upper .bubble {
|
||||
fill:none;
|
||||
stroke:#336699;
|
||||
stroke-opacity:1;
|
||||
}
|
||||
.Upper .leaderLine {
|
||||
fill:#336699;
|
||||
fill-opacity:1;
|
||||
stroke:none;
|
||||
}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<g id="IconChat">
|
||||
<g class="Lower" style="display:inline">
|
||||
<path class="bubble"
|
||||
d="M 15,8 A 6,5 0 1 1 3,8 6,5 0 1 1 15,8 z"
|
||||
transform="matrix(1.0345788,0,0,0.95089627,-1.510083,0.10801843)" />
|
||||
<path class="leaderLine"
|
||||
d="m 3.9001344,11.947742 c 0.075049,1.120603 -0.7948094,1.693805 -1.4915533,2.143417 1.0104403,
|
||||
0.104041 3.4597063,-0.953975 3.9167086,-1.276108 0.00808,-0.0057 -2.4251553,-0.867309 -2.4251553,-0.867309 z" />
|
||||
</g>
|
||||
|
||||
<g class="Upper" style="display:inline">
|
||||
<path class="bubble"
|
||||
d="M 15,8 A 6,5 0 1 1 3,8 6,5 0 1 1 15,8 z"
|
||||
transform="matrix(1.0345788,0,0,0.95089627,-1.5100816,-0.50773368)" />
|
||||
<path class="leaderLine"
|
||||
d="m 3.9001358,11.331991 c 0.075049,1.120603 -0.7948094,1.693805 -1.4915533,2.143417 1.0104403,
|
||||
0.104041 3.4597063,-0.953975 3.9167086,-1.276108 0.00808,-0.0057 -2.4251553,-0.867309 -2.4251553,-0.867309 z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -9,12 +9,18 @@
|
||||
|
||||
TimWolla ?= {}
|
||||
TimWolla.WCF ?= {}
|
||||
consoleMock = console
|
||||
consoleMock ?=
|
||||
log: () ->,
|
||||
warn: () ->
|
||||
warn: () ->,
|
||||
error: () ->
|
||||
|
||||
(($, window, console) ->
|
||||
TimWolla.WCF.Chat =
|
||||
# Tims Chat stops loading when this reaches zero
|
||||
# TODO: We need an explosion animation
|
||||
shields: 3
|
||||
|
||||
# Templates
|
||||
titleTemplate: null
|
||||
messageTemplate: null
|
||||
@ -34,17 +40,21 @@ consoleMock ?=
|
||||
events:
|
||||
newMessage: $.Callbacks()
|
||||
userMenu: $.Callbacks()
|
||||
pe:
|
||||
getMessages: null
|
||||
refreshRoomList: null
|
||||
fish: null
|
||||
init: () ->
|
||||
console.log '[TimWolla.WCF.Chat] Initializing'
|
||||
@bindEvents()
|
||||
@events.newMessage.add $.proxy @notify, @
|
||||
|
||||
new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, @), 60e3
|
||||
new WCF.PeriodicalExecuter $.proxy(@getMessages, @), @config.reloadTime * 1e3
|
||||
@pe.refreshRoomList = new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, @), 60e3
|
||||
@pe.getMessages = new WCF.PeriodicalExecuter $.proxy(@getMessages, @), @config.reloadTime * 1e3
|
||||
@refreshRoomList()
|
||||
@getMessages()
|
||||
|
||||
console.log '[TimWolla.WCF.Chat] Finished initializing'
|
||||
console.log '[TimWolla.WCF.Chat] Finished initializing - Shields at 104 percent'
|
||||
###
|
||||
# Autocompletes a username
|
||||
###
|
||||
@ -64,6 +74,7 @@ consoleMock ?=
|
||||
# Binds all the events needed for Tims Chat.
|
||||
###
|
||||
bindEvents: () ->
|
||||
# Mark window as focused
|
||||
$(window).focus $.proxy () ->
|
||||
document.title = @titleTemplate.fetch
|
||||
title: $('#timsChatRoomList .activeMenuItem a').text()
|
||||
@ -71,12 +82,19 @@ consoleMock ?=
|
||||
@isActive = true
|
||||
, @
|
||||
|
||||
# Mark window as blurred
|
||||
$(window).blur $.proxy () ->
|
||||
@isActive = false
|
||||
, @
|
||||
|
||||
# Unload the chat
|
||||
window.onbeforeunload = $.proxy () ->
|
||||
@unload()
|
||||
return undefined
|
||||
, @
|
||||
|
||||
# Insert a smiley
|
||||
$('.smiley').click $.proxy (event) ->
|
||||
$('.jsSmiley').click $.proxy (event) ->
|
||||
@insertText ' ' + $(event.target).attr('alt') + ' '
|
||||
, @
|
||||
|
||||
@ -118,11 +136,11 @@ consoleMock ?=
|
||||
|
||||
# Clears the stream
|
||||
$('#timsChatClear').click (event) ->
|
||||
event.preventDefault()
|
||||
$('.timsChatMessage').remove()
|
||||
@oldScrollTop = $('.timsChatMessageContainer').scrollTop()
|
||||
$('.timsChatMessageContainer').scrollTop $('.timsChatMessageContainer ul').height()
|
||||
$('#timsChatInput').focus()
|
||||
event.preventDefault()
|
||||
$('.timsChatMessage').remove()
|
||||
@oldScrollTop = null
|
||||
$('.timsChatMessageContainer').scrollTop $('.timsChatMessageContainer ul').height()
|
||||
$('#timsChatInput').focus()
|
||||
|
||||
# Toggle Buttons
|
||||
$('.timsChatToggle').click (event) ->
|
||||
@ -139,7 +157,7 @@ consoleMock ?=
|
||||
|
||||
# Immediatly scroll down when activating autoscroll
|
||||
$('#timsChatAutoscroll').click (event) ->
|
||||
$(this).removeClass('hot')
|
||||
$(this).parent().removeClass('default')
|
||||
if $(this).data 'status'
|
||||
$('.timsChatMessageContainer').scrollTop $('.timsChatMessageContainer ul').height()
|
||||
@oldScrollTop = $('.timsChatMessageContainer').scrollTop()
|
||||
@ -172,15 +190,15 @@ consoleMock ?=
|
||||
|
||||
# Set new topic
|
||||
if data.topic is ''
|
||||
return if $('#topic').text().trim() is ''
|
||||
return if $('#timsChatTopic').text().trim() is ''
|
||||
|
||||
$('#topic').wcfBlindOut 'vertical', () ->
|
||||
$('#timsChatTopic').wcfBlindOut 'vertical', () ->
|
||||
$(@).text ''
|
||||
else
|
||||
$('#topic').text data.topic
|
||||
$('#topic').wcfBlindIn() if $('#topic').text().trim() isnt '' and $('#topic').is(':hidden')
|
||||
$('#timsChatTopic').text data.topic
|
||||
$('#timsChatTopic').wcfBlindIn() if $('#timsChatTopic').text().trim() isnt '' and $('#timsChatTopic').is(':hidden')
|
||||
|
||||
$('.timsChatMessage').animate('opacity', .8);
|
||||
$('.timsChatMessage').addClass('unloaded', 800);
|
||||
@handleMessages data.messages
|
||||
document.title = @titleTemplate.fetch data
|
||||
, @)
|
||||
@ -198,7 +216,7 @@ consoleMock ?=
|
||||
# Frees the fish
|
||||
###
|
||||
freeTheFish: () ->
|
||||
return if $.wcfIsset('fish')
|
||||
return if $.wcfIsset 'fish'
|
||||
console.warn '[TimWolla.WCF.Chat] Freeing the fish'
|
||||
fish = $ '<div id="fish">' + WCF.String.escapeHTML('><((((\u00B0>') + '</div>'
|
||||
fish.css
|
||||
@ -210,16 +228,16 @@ consoleMock ?=
|
||||
zIndex: 9999
|
||||
|
||||
fish.appendTo $ 'body'
|
||||
new WCF.PeriodicalExecuter(() ->
|
||||
@pe.fish = new WCF.PeriodicalExecuter(() ->
|
||||
left = Math.random() * 100 - 50
|
||||
top = Math.random() * 100 - 50
|
||||
fish = $('#fish')
|
||||
fish = $ '#fish'
|
||||
|
||||
left *= -1 unless fish.width() < (fish.position().left + left) < ($(document).width() - fish.width())
|
||||
top *= -1 unless fish.height() < (fish.position().top + top) < ($(document).height() - fish.height())
|
||||
|
||||
fish.text('><((((\u00B0>') if left > 0
|
||||
fish.text('<\u00B0))))><') if left < 0
|
||||
fish.text '><((((\u00B0>' if left > 0
|
||||
fish.text '<\u00B0))))><' if left < 0
|
||||
|
||||
fish.animate
|
||||
top: '+=' + top
|
||||
@ -237,6 +255,15 @@ consoleMock ?=
|
||||
@handleMessages(data.messages)
|
||||
@handleUsers(data.users)
|
||||
, @)
|
||||
error: $.proxy((jqXHR, textStatus, errorThrown) ->
|
||||
console.error '[TimWolla.WCF.Chat] Battle Station hit - shields at ' + (--@shields / 3 * 104) + ' percent'
|
||||
if @shields is 0
|
||||
@pe.refreshRoomList.stop()
|
||||
@pe.getMessages.stop()
|
||||
@freeTheFish()
|
||||
console.error '[TimWolla.WCF.Chat] We got destroyed, but could free our friend the fish before he was killed as well. Have a nice life in freedom!'
|
||||
alert 'herp i cannot load messages'
|
||||
, @)
|
||||
###
|
||||
# Inserts the new messages.
|
||||
#
|
||||
@ -248,14 +275,16 @@ consoleMock ?=
|
||||
if $('.timsChatMessageContainer').scrollTop() < @oldScrollTop
|
||||
if $('#timsChatAutoscroll').data('status') is 1
|
||||
$('#timsChatAutoscroll').click()
|
||||
$('#timsChatAutoscroll').addClass('hot').fadeOut('slow').fadeIn('slow')
|
||||
$('#timsChatAutoscroll').parent().addClass('default').fadeOut('slow').fadeIn('slow')
|
||||
|
||||
# Insert the messages
|
||||
for message in messages
|
||||
continue if $.wcfIsset 'timsChatMessage'+message.messageID # Prevent problems with race condition
|
||||
@events.newMessage.fire message
|
||||
|
||||
output = @messageTemplate.fetch message
|
||||
li = $ '<li></li>'
|
||||
li.attr 'id', 'timsChatMessage'+message.messageID
|
||||
li.addClass 'timsChatMessage timsChatMessage'+message.type
|
||||
li.addClass 'ownMessage' if message.sender is WCF.User.userID
|
||||
li.append output
|
||||
@ -314,7 +343,7 @@ consoleMock ?=
|
||||
$(@).remove();
|
||||
|
||||
|
||||
$('#toggleUsers .badge').text(users.length);
|
||||
$('#toggleUsers .wcf-badge').text(users.length);
|
||||
###
|
||||
# Inserts text into our input.
|
||||
#
|
||||
@ -371,7 +400,7 @@ consoleMock ?=
|
||||
success: $.proxy((data, textStatus, jqXHR) ->
|
||||
$('#timsChatRoomList li').remove()
|
||||
$('#toggleRooms a').removeClass 'ajaxLoad'
|
||||
$('#toggleRooms .badge').text(data.length);
|
||||
$('#toggleRooms .wcf-badge').text(data.length);
|
||||
|
||||
for room in data
|
||||
li = $ '<li></li>'
|
||||
@ -447,4 +476,11 @@ consoleMock ?=
|
||||
else
|
||||
li.addClass 'activeMenuItem'
|
||||
li.find('.timsChatUserMenu').wcfBlindIn 'vertical'
|
||||
###
|
||||
# Unloads the chat.
|
||||
###
|
||||
unload: () ->
|
||||
$.ajax @config.unloadURL,
|
||||
type: 'POST'
|
||||
async: false
|
||||
)(jQuery, @, consoleMock)
|
||||
|
149
file/lib/acp/form/ChatRoomAddForm.class.php
Normal file
149
file/lib/acp/form/ChatRoomAddForm.class.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
namespace wcf\acp\form;
|
||||
use \wcf\system\exception\UserInputException;
|
||||
use \wcf\system\language\I18nHandler;
|
||||
use \wcf\system\package\PackageDependencyHandler;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Shows the chatroom add form.
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage acp.form
|
||||
*/
|
||||
class ChatRoomAddForm extends ACPForm {
|
||||
/**
|
||||
* @see \wcf\acp\form\ACPForm::$activeMenuItem
|
||||
*/
|
||||
public $activeMenuItem = 'wcf.acp.menu.link.chat.room.add';
|
||||
|
||||
/**
|
||||
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||
*/
|
||||
public $neededPermissions = array('admin.content.chat.canAddRoom');
|
||||
|
||||
/**
|
||||
* Title of the room
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
/**
|
||||
* Topic of the room
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $topic = '';
|
||||
|
||||
/**
|
||||
* @see \wcf\page\AbstractPage::__construct()
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->objectTypeID = \wcf\system\acl\ACLHandler::getInstance()->getObjectTypeID('timwolla.wcf.chat.room');
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::readParameters()
|
||||
*/
|
||||
public function readParameters() {
|
||||
parent::readParameters();
|
||||
|
||||
I18nHandler::getInstance()->register('title');
|
||||
I18nHandler::getInstance()->register('topic');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\IForm::readFormParameters()
|
||||
*/
|
||||
public function readFormParameters() {
|
||||
parent::readFormParameters();
|
||||
|
||||
I18nHandler::getInstance()->readValues();
|
||||
|
||||
if (I18nHandler::getInstance()->isPlainValue('title')) $this->title = I18nHandler::getInstance()->getValue('title');
|
||||
if (I18nHandler::getInstance()->isPlainValue('topic')) $this->topic = I18nHandler::getInstance()->getValue('topic');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\IForm::validate()
|
||||
*/
|
||||
public function validate() {
|
||||
parent::validate();
|
||||
|
||||
// validate title
|
||||
if (!I18nHandler::getInstance()->validateValue('title')) {
|
||||
throw new UserInputException('title');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\IForm::save()
|
||||
*/
|
||||
public function save() {
|
||||
parent::save();
|
||||
|
||||
// save room
|
||||
$this->objectAction = new \wcf\data\chat\room\ChatRoomAction(array(), 'create', array('data' => array(
|
||||
'title' => $this->title,
|
||||
'topic' => $this->topic
|
||||
)));
|
||||
$this->objectAction->executeAction();
|
||||
$returnValues = $this->objectAction->getReturnValues();
|
||||
$chatRoomEditor = new \wcf\data\chat\room\ChatRoomEditor($returnValues['returnValues']);
|
||||
$roomID = $returnValues['returnValues']->roomID;
|
||||
|
||||
if (!I18nHandler::getInstance()->isPlainValue('title')) {
|
||||
I18nHandler::getInstance()->save('title', 'wcf.chat.room.title'.$roomID, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
|
||||
|
||||
// update title
|
||||
$chatRoomEditor->update(array(
|
||||
'title' => 'wcf.chat.room.title'.$roomID
|
||||
));
|
||||
}
|
||||
|
||||
if (!I18nHandler::getInstance()->isPlainValue('topic')) {
|
||||
I18nHandler::getInstance()->save('topic', 'wcf.chat.room.topic'.$roomID, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
|
||||
|
||||
// update topic
|
||||
$chatRoomEditor->update(array(
|
||||
'topic' => 'wcf.chat.room.topic'.$roomID
|
||||
));
|
||||
}
|
||||
|
||||
\wcf\system\acl\ACLHandler::getInstance()->save($roomID, $this->objectTypeID);
|
||||
\wcf\system\chat\permission\ChatPermissionHandler::clearCache();
|
||||
|
||||
$this->saved();
|
||||
|
||||
// reset values
|
||||
$this->topic = $this->title = '';
|
||||
I18nHandler::getInstance()->disableAssignValueVariables();
|
||||
|
||||
// show success
|
||||
WCF::getTPL()->assign(array(
|
||||
'success' => true
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::assignVariables()
|
||||
*/
|
||||
public function assignVariables() {
|
||||
parent::assignVariables();
|
||||
|
||||
I18nHandler::getInstance()->assignVariables();
|
||||
|
||||
WCF::getTPL()->assign(array(
|
||||
'action' => 'add',
|
||||
'title' => $this->title,
|
||||
'topic' => $this->topic,
|
||||
'objectTypeID' => $this->objectTypeID
|
||||
));
|
||||
}
|
||||
}
|
129
file/lib/acp/form/ChatRoomEditForm.class.php
Normal file
129
file/lib/acp/form/ChatRoomEditForm.class.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
namespace wcf\acp\form;
|
||||
use wcf\system\language\I18nHandler;
|
||||
use wcf\system\package\PackageDependencyHandler;
|
||||
use wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Shows the chatroom edit form.
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage acp.form
|
||||
*/
|
||||
class ChatRoomEditForm extends ChatRoomAddForm {
|
||||
/**
|
||||
* @see \wcf\page\AbstractPage::$templateName
|
||||
*/
|
||||
public $templateName = 'chatRoomAdd';
|
||||
|
||||
/**
|
||||
* @see \wcf\acp\form\ACPForm::$activeMenuItem
|
||||
*/
|
||||
public $activeMenuItem = 'wcf.acp.menu.link.chat.room.list';
|
||||
|
||||
/**
|
||||
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||
*/
|
||||
public $neededPermissions = array('admin.content.chat.canEditRoom');
|
||||
|
||||
/**
|
||||
* room id
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $roomID = 0;
|
||||
|
||||
/**
|
||||
* room object
|
||||
*
|
||||
* @var \wcf\data\chat\room\ChatRoom
|
||||
*/
|
||||
public $roomObj = null;
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::readParameters()
|
||||
*/
|
||||
public function readParameters() {
|
||||
parent::readParameters();
|
||||
|
||||
if (isset($_REQUEST['id'])) $this->roomID = intval($_REQUEST['id']);
|
||||
$this->roomObj = new \wcf\data\chat\room\ChatRoom($this->roomID);
|
||||
if (!$this->roomObj->roomID) {
|
||||
throw new \wcf\system\exception\IllegalLinkException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\IForm::save()
|
||||
*/
|
||||
public function save() {
|
||||
ACPForm::save();
|
||||
|
||||
$this->title = 'wcf.chat.room.title'.$this->roomObj->roomID;
|
||||
if (I18nHandler::getInstance()->isPlainValue('title')) {
|
||||
I18nHandler::getInstance()->remove($this->title, PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
|
||||
$this->title = I18nHandler::getInstance()->getValue('title');
|
||||
}
|
||||
else {
|
||||
I18nHandler::getInstance()->save('title', $this->title, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
|
||||
}
|
||||
|
||||
$this->topic = 'wcf.chat.room.topic'.$this->roomObj->roomID;
|
||||
if (I18nHandler::getInstance()->isPlainValue('topic')) {
|
||||
I18nHandler::getInstance()->remove($this->topic, PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
|
||||
$this->topic = I18nHandler::getInstance()->getValue('topic');
|
||||
}
|
||||
else {
|
||||
I18nHandler::getInstance()->save('topic', $this->topic, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
|
||||
}
|
||||
|
||||
\wcf\system\acl\ACLHandler::getInstance()->save($this->roomID, $this->objectTypeID);
|
||||
\wcf\system\chat\permission\ChatPermissionHandler::clearCache();
|
||||
|
||||
// update room
|
||||
$this->objectAction = new \wcf\data\chat\room\ChatRoomAction(array($this->roomID), 'update', array('data' => array(
|
||||
'title' => $this->title,
|
||||
'topic' => $this->topic
|
||||
)));
|
||||
$this->objectAction->executeAction();
|
||||
|
||||
$this->saved();
|
||||
|
||||
// show success
|
||||
WCF::getTPL()->assign(array(
|
||||
'success' => true
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::readData()
|
||||
*/
|
||||
public function readData() {
|
||||
parent::readData();
|
||||
|
||||
if (!count($_POST)) {
|
||||
I18nHandler::getInstance()->setOptions('title', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'), $this->roomObj->title, 'wcf.chat.room.title\d+');
|
||||
I18nHandler::getInstance()->setOptions('topic', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'), $this->roomObj->topic, 'wcf.chat.room.topic\d+');
|
||||
|
||||
$this->title = $this->roomObj->title;
|
||||
$this->topic = $this->roomObj->topic;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::assignVariables()
|
||||
*/
|
||||
public function assignVariables() {
|
||||
parent::assignVariables();
|
||||
|
||||
I18nHandler::getInstance()->assignVariables((bool) count($_POST));
|
||||
|
||||
WCF::getTPL()->assign(array(
|
||||
'roomID' => $this->roomID,
|
||||
'action' => 'edit'
|
||||
));
|
||||
}
|
||||
}
|
46
file/lib/acp/page/ChatRoomListPage.class.php
Normal file
46
file/lib/acp/page/ChatRoomListPage.class.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace wcf\acp\page;
|
||||
|
||||
/**
|
||||
* Lists available chatrooms.
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage acp.page
|
||||
*/
|
||||
class ChatRoomListPage extends \wcf\page\MultipleLinkPage {
|
||||
/**
|
||||
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||
*/
|
||||
public $neededPermissions = array(
|
||||
'admin.content.chat.canEditRoom',
|
||||
'admin.content.chat.canDeleteRoom'
|
||||
);
|
||||
|
||||
/**
|
||||
* @see \wcf\page\MultipleLinkPage::$objectListClassName
|
||||
*/
|
||||
public $objectListClassName = '\wcf\data\chat\room\ChatRoomList';
|
||||
|
||||
/**
|
||||
* @see \wcf\page\MultipleLinkPage::$sortField
|
||||
*/
|
||||
public $sortField = 'position';
|
||||
|
||||
/**
|
||||
* @see \wcf\page\MultipleLinkPage::$sortOrder
|
||||
*/
|
||||
public $sortOrder = 'ASC';
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::show()
|
||||
*/
|
||||
public function show() {
|
||||
// set active menu item.
|
||||
\wcf\system\menu\acp\ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.chat.room.list');
|
||||
|
||||
parent::show();
|
||||
}
|
||||
}
|
65
file/lib/action/ChatLeaveAction.class.php
Normal file
65
file/lib/action/ChatLeaveAction.class.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
namespace wcf\action;
|
||||
use \wcf\data\chat;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Makes the user leave Tims Chat.
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage action
|
||||
*/
|
||||
class ChatLeaveAction extends AbstractAction {
|
||||
/**
|
||||
* @see \wcf\action\AbstractAction::$neededModules
|
||||
*/
|
||||
public $neededModules = array('CHAT_ACTIVE');
|
||||
//public $neededPermissions = array('user.chat.canEnter');
|
||||
public $room = null;
|
||||
public $userData = array();
|
||||
|
||||
/**
|
||||
* @see \wcf\action\IAction::execute()
|
||||
*/
|
||||
public function execute() {
|
||||
parent::execute();
|
||||
|
||||
// validate
|
||||
if (!WCF::getUser()->userID) {
|
||||
throw new IllegalLinkException();
|
||||
}
|
||||
|
||||
$this->userData['roomID'] = \wcf\util\ChatUtil::readUserData('roomID');
|
||||
|
||||
$this->room = chat\room\ChatRoom::getCache()->search($this->userData['roomID']);
|
||||
if (!$this->room) throw new \wcf\system\exception\IllegalLinkException();
|
||||
if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||
|
||||
if (CHAT_DISPLAY_JOIN_LEAVE) {
|
||||
$this->userData['color'] = \wcf\util\ChatUtil::readUserData('color');
|
||||
|
||||
$messageAction = new chat\message\ChatMessageAction(array(), 'create', array(
|
||||
'data' => array(
|
||||
'roomID' => $this->room->roomID,
|
||||
'sender' => WCF::getUser()->userID,
|
||||
'username' => WCF::getUser()->username,
|
||||
'time' => TIME_NOW,
|
||||
'type' => chat\message\ChatMessage::TYPE_LEAVE,
|
||||
'message' => '',
|
||||
'color1' => $this->userData['color'][1],
|
||||
'color2' => $this->userData['color'][2]
|
||||
)
|
||||
));
|
||||
$messageAction->executeAction();
|
||||
}
|
||||
|
||||
\wcf\util\ChatUtil::writeUserData(array('roomID' => null));
|
||||
|
||||
$this->executed();
|
||||
header("HTTP/1.0 204 No Content");
|
||||
exit;
|
||||
}
|
||||
}
|
@ -13,12 +13,12 @@ use \wcf\system\WCF;
|
||||
*/
|
||||
class ChatMessage extends \wcf\data\DatabaseObject {
|
||||
/**
|
||||
* @see wcf\data\DatabaseObject::$databaseTableName
|
||||
* @see \wcf\data\DatabaseObject::$databaseTableName
|
||||
*/
|
||||
protected static $databaseTableName = 'chat_message';
|
||||
|
||||
/**
|
||||
* @see wcf\data\DatabaseObject::$databaseTableIndexName
|
||||
* @see \wcf\data\DatabaseObject::$databaseTableIndexName
|
||||
*/
|
||||
protected static $databaseTableIndexName = 'messageID';
|
||||
|
||||
@ -110,7 +110,8 @@ class ChatMessage extends \wcf\data\DatabaseObject {
|
||||
'time' => $this->time,
|
||||
'receiver' => $this->receiver,
|
||||
'type' => $this->type,
|
||||
'roomID' => $this->roomID
|
||||
'roomID' => $this->roomID,
|
||||
'messageID' => $this->messageID
|
||||
);
|
||||
|
||||
if ($raw) return $array;
|
||||
|
@ -12,7 +12,7 @@ namespace wcf\data\chat\message;
|
||||
*/
|
||||
class ChatMessageAction extends \wcf\data\AbstractDatabaseObjectAction {
|
||||
/**
|
||||
* @see wcf\data\AbstractDatabaseObjectAction::$className
|
||||
* @see \wcf\data\AbstractDatabaseObjectAction::$className
|
||||
*/
|
||||
protected $className = '\wcf\data\chat\message\ChatMessageEditor';
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace wcf\data\chat\message;
|
||||
*/
|
||||
class ChatMessageEditor extends \wcf\data\DatabaseObjectEditor {
|
||||
/**
|
||||
* @see wcf\data\DatabaseObjectDecorator::$baseClass
|
||||
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
|
||||
*/
|
||||
protected static $baseClass = '\wcf\data\chat\message\ChatMessage';
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace wcf\data\chat\message;
|
||||
*/
|
||||
class ChatMessageList extends \wcf\data\DatabaseObjectList {
|
||||
/**
|
||||
* @see wcf\data\DatabaseObjectList::$className
|
||||
* @see \wcf\data\DatabaseObjectList::$className
|
||||
*/
|
||||
public $className = 'wcf\data\chat\message\ChatMessage';
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace wcf\data\chat\room;
|
||||
use \wcf\system\cache\CacheHandler;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Represents a chat room.
|
||||
@ -13,12 +14,12 @@ use \wcf\system\cache\CacheHandler;
|
||||
*/
|
||||
class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\IRouteController {
|
||||
/**
|
||||
* @see wcf\data\DatabaseObject::$databaseTableName
|
||||
* @see \wcf\data\DatabaseObject::$databaseTableName
|
||||
*/
|
||||
protected static $databaseTableName = 'chat_room';
|
||||
|
||||
/**
|
||||
* @see wcf\data\DatabaseObject::$databaseTableIndexName
|
||||
* @see \wcf\data\DatabaseObject::$databaseTableIndexName
|
||||
*/
|
||||
protected static $databaseTableIndexName = 'roomID';
|
||||
|
||||
@ -29,6 +30,36 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
|
||||
*/
|
||||
protected static $cache = null;
|
||||
|
||||
/**
|
||||
* @see \wcf\data\chat\room\ChatRoom::getTitle();
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->getTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of users currently active in this room.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function countUsers() {
|
||||
$packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
|
||||
|
||||
$sql = "SELECT
|
||||
count(*) as count
|
||||
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();
|
||||
|
||||
return $row['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the room cache.
|
||||
*/
|
||||
@ -37,7 +68,7 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
|
||||
CacheHandler::getInstance()->addResource(
|
||||
'chatrooms',
|
||||
WCF_DIR.'cache/cache.chatrooms.php',
|
||||
'wcf\system\cache\builder\ChatRoomCacheBuilder'
|
||||
'\wcf\system\cache\builder\ChatRoomCacheBuilder'
|
||||
);
|
||||
self::$cache = CacheHandler::getInstance()->get('chatrooms');
|
||||
}
|
||||
@ -46,10 +77,12 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\data\chat\room\ChatRoom::getTitle();
|
||||
* Returns the ID of this chat-room.
|
||||
*
|
||||
* @see \wcf\system\request\IRouteController
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->getTitle();
|
||||
public function getID() {
|
||||
return $this->roomID;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,12 +95,39 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this chat-room.
|
||||
*
|
||||
* @see \wcf\system\request\RRouteHandler
|
||||
* Returns the users that are currently active in this room.
|
||||
*
|
||||
* @return array<\wcf\data\user\User>
|
||||
*/
|
||||
public function getID() {
|
||||
return $this->roomID;
|
||||
public function getUsers() {
|
||||
$packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
|
||||
|
||||
$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();
|
||||
$userIDs = array();
|
||||
while ($row = $stmt->fetchArray()) $userIDs[] = $row['userID'];
|
||||
|
||||
if (!count($userIDs)) return;
|
||||
|
||||
$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);
|
||||
return $stmt->fetchObjects('\wcf\data\user\User');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,6 +136,8 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEnter() {
|
||||
return \wcf\system\chat\permissions\ChatPermissionHandler::getInstance()->getPermission($this, 'canEnter');
|
||||
$ph = \wcf\system\chat\permission\ChatPermissionHandler::getInstance();
|
||||
|
||||
return $ph->getPermission($this, 'user.canEnter') || $ph->getPermission($this, 'mod.canAlwaysEnter');
|
||||
}
|
||||
}
|
||||
|
95
file/lib/data/chat/room/ChatRoomAction.class.php
Normal file
95
file/lib/data/chat/room/ChatRoomAction.class.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace wcf\data\chat\room;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Executes chatroom-related actions.
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage data.chat.room
|
||||
*/
|
||||
class ChatRoomAction extends \wcf\data\AbstractDatabaseObjectAction {
|
||||
/**
|
||||
* @see \wcf\data\AbstractDatabaseObjectAction::$className
|
||||
*/
|
||||
protected $className = '\wcf\data\chat\room\ChatRoomEditor';
|
||||
|
||||
/**
|
||||
* @see \wcf\data\AbstractDatabaseObjectAction::$permissionsDelete
|
||||
*/
|
||||
protected $permissionsDelete = array('admin.content.chat.canDeleteRoom');
|
||||
|
||||
/**
|
||||
* @see \wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate
|
||||
*/
|
||||
protected $permissionsUpdate = array('admin.content.chat.canEditRoom');
|
||||
|
||||
/**
|
||||
* Fixes create to append new boards.
|
||||
*/
|
||||
public function create() {
|
||||
$room = parent::create();
|
||||
|
||||
WCF::getDB()->beginTransaction();
|
||||
$sql = "SELECT max(position) as max
|
||||
FROM wcf".WCF_N."_chat_room
|
||||
FOR UPDATE";
|
||||
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetchArray();
|
||||
|
||||
$sql = "UPDATE wcf".WCF_N."_chat_room
|
||||
SET position = ".($row['max'] + 1)."
|
||||
WHERE roomID = ?";
|
||||
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||
$stmt->execute(array($room->roomID));
|
||||
WCF::getDB()->commitTransaction();
|
||||
|
||||
return $room;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates parameters to update sorting.
|
||||
*/
|
||||
public function validateUpdatePosition() {
|
||||
// validate permissions
|
||||
if (is_array($this->permissionsUpdate) && count($this->permissionsUpdate)) {
|
||||
try {
|
||||
WCF::getSession()->checkPermissions($this->permissionsUpdate);
|
||||
}
|
||||
catch (\wcf\system\exception\PermissionDeniedException $e) {
|
||||
throw new ValidateActionException('Insufficient permissions');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new ValidateActionException('Insufficient permissions');
|
||||
}
|
||||
|
||||
if (!isset($this->parameters['data']['structure'])) {
|
||||
throw new ValidateActionException('Missing parameter structure');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates sorting.
|
||||
*/
|
||||
public function updatePosition() {
|
||||
$roomList = new \wcf\data\chat\room\ChatRoomList();
|
||||
$roomList->sqlOrderBy = "chat_room.position";
|
||||
$roomList->sqlLimit = 0;
|
||||
$roomList->readObjects();
|
||||
|
||||
$i = 0;
|
||||
WCF::getDB()->beginTransaction();
|
||||
foreach ($this->parameters['data']['structure'][0] as $roomID) {
|
||||
$room = $roomList->search($roomID);
|
||||
if ($room === null) continue;
|
||||
$editor = new ChatRoomEditor($room);
|
||||
$editor->update(array('position' => $i++));
|
||||
}
|
||||
WCF::getDB()->commitTransaction();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace wcf\data\chat\room;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Provides functions to edit chat rooms.
|
||||
@ -12,7 +13,7 @@ namespace wcf\data\chat\room;
|
||||
*/
|
||||
class ChatRoomEditor extends \wcf\data\DatabaseObjectEditor implements \wcf\data\IEditableCachedObject {
|
||||
/**
|
||||
* @see wcf\data\DatabaseObjectDecorator::$baseClass
|
||||
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
|
||||
*/
|
||||
protected static $baseClass = '\wcf\data\chat\room\ChatRoom';
|
||||
|
||||
@ -20,7 +21,23 @@ class ChatRoomEditor extends \wcf\data\DatabaseObjectEditor implements \wcf\data
|
||||
* Clears the room cache.
|
||||
*/
|
||||
public static function resetCache() {
|
||||
self::getCache();
|
||||
CacheHandler::getInstance()->clearResource('chatrooms');
|
||||
\wcf\system\cache\CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.chatrooms.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\data\DatabaseObjectEditor::deleteAll()
|
||||
*/
|
||||
public static function deleteAll(array $objectIDs = array()) {
|
||||
parent::deleteAll($objectIDs);
|
||||
$packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
|
||||
|
||||
WCF::getDB()->beginTransaction();
|
||||
foreach ($objectIDs as $objectID) {
|
||||
\wcf\system\language\I18nHandler::getInstance()->remove('wcf.chat.room.title'.$objectID, $packageID);
|
||||
\wcf\system\language\I18nHandler::getInstance()->remove('wcf.chat.room.topic'.$objectID, $packageID);
|
||||
}
|
||||
WCF::getDB()->commitTransaction();
|
||||
|
||||
return count($objectIDs);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace wcf\data\chat\room;
|
||||
*/
|
||||
class ChatRoomList extends \wcf\data\DatabaseObjectList {
|
||||
/**
|
||||
* @see wcf\data\DatabaseObjectList::$className
|
||||
* @see \wcf\data\DatabaseObjectList::$className
|
||||
*/
|
||||
public $className = 'wcf\data\chat\room\ChatRoom';
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
<?php
|
||||
namespace wcf\form;
|
||||
use \wcf\data\chat;
|
||||
use \wcf\system\exception\PermissionDeniedException;
|
||||
use \wcf\system\exception\UserInputException;
|
||||
use \wcf\system\WCF;
|
||||
use \wcf\util\StringUtil;
|
||||
|
||||
/**
|
||||
* Inserts a message
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
*
|
||||
* @author Tim Düsterhus
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
@ -20,10 +19,14 @@ class ChatForm extends AbstractForm {
|
||||
public $message = '';
|
||||
public $room = null;
|
||||
public $userData = array();
|
||||
|
||||
/**
|
||||
* @see \wcf\page\AbstractForm::$useTemplate
|
||||
*/
|
||||
public $useTemplate = false;
|
||||
|
||||
/**
|
||||
* @see \wcf\page\AbstractPage::readData()
|
||||
* @see \wcf\page\IPage::readData()
|
||||
*/
|
||||
public function readData() {
|
||||
$this->userData['color'] = \wcf\util\ChatUtil::readUserData('color');
|
||||
@ -37,17 +40,17 @@ class ChatForm extends AbstractForm {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\AbstractForm::readFormParameters()
|
||||
* @see \wcf\form\IForm::readFormParameters()
|
||||
*/
|
||||
public function readFormParameters() {
|
||||
parent::readFormParameters();
|
||||
|
||||
if (isset($_REQUEST['text'])) $this->message = StringUtil::trim($_REQUEST['text']);
|
||||
if (isset($_REQUEST['text'])) $this->message = \wcf\util\MessageUtil::stripCrap(StringUtil::trim($_REQUEST['text']));
|
||||
if (isset($_REQUEST['smilies'])) $this->enableSmilies = intval($_REQUEST['smilies']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\AbstractForm::validate()
|
||||
* @see \wcf\form\IForm::validate()
|
||||
*/
|
||||
public function validate() {
|
||||
parent::validate();
|
||||
@ -55,10 +58,14 @@ class ChatForm extends AbstractForm {
|
||||
if ($this->message === '') {
|
||||
throw new UserInputException('text');
|
||||
}
|
||||
|
||||
if (strlen($this->message) > CHAT_MAX_LENGTH) {
|
||||
throw new UserInputException('text', 'tooLong');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\form\AbstractForm::save()
|
||||
* @see \wcf\form\IForm::save()
|
||||
*/
|
||||
public function save() {
|
||||
parent::save();
|
||||
@ -107,4 +114,12 @@ class ChatForm extends AbstractForm {
|
||||
|
||||
$this->saved();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::show()
|
||||
*/
|
||||
public function show() {
|
||||
header("HTTP/1.0 204 No Content");
|
||||
parent::show();
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,14 @@ class ChatMessagePage extends AbstractPage {
|
||||
public $useTemplate = false;
|
||||
|
||||
/**
|
||||
* @see \wcf\page\Page::readData()
|
||||
* @see \wcf\page\Page::readData()
|
||||
*/
|
||||
public function readData() {
|
||||
parent::readData();
|
||||
|
||||
$this->readRoom();
|
||||
$this->readMessages();
|
||||
$this->readUsers();
|
||||
$this->users = $this->room->getUsers();
|
||||
}
|
||||
|
||||
public function readMessages() {
|
||||
@ -54,34 +54,6 @@ class ChatMessagePage extends AbstractPage {
|
||||
if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
|
||||
}
|
||||
|
||||
public function readUsers() {
|
||||
$packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
|
||||
|
||||
$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();
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \wcf\page\IPage::show()
|
||||
*/
|
||||
@ -94,6 +66,11 @@ class ChatMessagePage extends AbstractPage {
|
||||
parent::show();
|
||||
|
||||
@header('Content-type: application/json');
|
||||
// enable gzip compression
|
||||
if (HTTP_ENABLE_GZIP && HTTP_GZIP_LEVEL > 0 && HTTP_GZIP_LEVEL < 10 && !defined('HTTP_DISABLE_GZIP')) {
|
||||
\wcf\util\HeaderUtil::compressOutput();
|
||||
}
|
||||
|
||||
$json = array('users' => array(), 'messages' => array());
|
||||
|
||||
foreach ($this->messages as $message) {
|
||||
|
@ -105,25 +105,24 @@ class ChatPage extends AbstractPage {
|
||||
public function readParameters() {
|
||||
parent::readParameters();
|
||||
|
||||
if ($this->action == 'Message') {
|
||||
new ChatMessagePage();
|
||||
exit;
|
||||
}
|
||||
else if ($this->action == 'Log') {
|
||||
//TODO: Initialise LogPage
|
||||
exit;
|
||||
}
|
||||
else if ($this->action == 'RefreshRoomList') {
|
||||
new ChatRefreshRoomListPage();
|
||||
exit;
|
||||
}
|
||||
else if ($this->action == 'Send') {
|
||||
new \wcf\form\ChatForm();
|
||||
exit;
|
||||
}
|
||||
else if ($this->action == 'Copyright') {
|
||||
new ChatCopyrightPage();
|
||||
exit;
|
||||
switch ($this->action) {
|
||||
case 'Message':
|
||||
new ChatMessagePage();
|
||||
exit;
|
||||
case 'Log':
|
||||
exit;
|
||||
case 'RefreshRoomList':
|
||||
new ChatRefreshRoomListPage();
|
||||
exit;
|
||||
case 'Send':
|
||||
new \wcf\form\ChatForm();
|
||||
exit;
|
||||
case 'Leave':
|
||||
new \wcf\action\ChatLeaveAction();
|
||||
exit;
|
||||
case 'Copyright':
|
||||
new ChatCopyrightPage();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['id'])) $this->roomID = (int) $_REQUEST['id'];
|
||||
|
44
file/lib/system/cache/builder/ChatPermissionCacheBuilder.class.php
vendored
Normal file
44
file/lib/system/cache/builder/ChatPermissionCacheBuilder.class.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace wcf\system\cache\builder;
|
||||
use wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Caches the chat permissions for a combination of user groups.
|
||||
*
|
||||
* @author Tim Düsterhus, Marcel Werk
|
||||
* @copyright 2010-2012 WoltLab GmbH
|
||||
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage system.cache.builder
|
||||
*/
|
||||
class ChatPermissionCacheBuilder implements ICacheBuilder {
|
||||
/**
|
||||
* @see wcf\system\cache\ICacheBuilder::getData()
|
||||
*/
|
||||
public function getData(array $cacheResource) {
|
||||
$data = array();
|
||||
list(, $groupIDsStr) = explode('-', $cacheResource['cache']);
|
||||
$groupIDs = explode(',', $groupIDsStr);
|
||||
|
||||
if (count($groupIDs)) {
|
||||
$conditionBuilder = new \wcf\system\database\util\PreparedStatementConditionBuilder();
|
||||
$conditionBuilder->add('acl_option.packageID IN (?)', array(\wcf\system\package\PackageDependencyHandler::getDependencies()));
|
||||
$conditionBuilder->add('acl_option.objectTypeID = ?', array(\wcf\system\acl\ACLHandler::getInstance()->getObjectTypeID('timwolla.wcf.chat.room')));
|
||||
$conditionBuilder->add('option_to_group.optionID = acl_option.optionID');
|
||||
$conditionBuilder->add('option_to_group.groupID IN (?)', array($groupIDs));
|
||||
$sql = "SELECT option_to_group.groupID, option_to_group.objectID AS roomID, option_to_group.optionValue,
|
||||
acl_option.optionName AS permission
|
||||
FROM wcf".WCF_N."_acl_option acl_option,
|
||||
wcf".WCF_N."_acl_option_to_group option_to_group
|
||||
".$conditionBuilder;
|
||||
$statement = WCF::getDB()->prepareStatement($sql);
|
||||
$statement->execute($conditionBuilder->getParameters());
|
||||
while ($row = $statement->fetchArray()) {
|
||||
if (!isset($data[$row['roomID']][$row['permission']])) $data[$row['roomID']][$row['permission']] = $row['optionValue'];
|
||||
else $data[$row['roomID']][$row['permission']] = $row['optionValue'] || $data[$row['roomID']][$row['permission']];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ namespace wcf\system\cache\builder;
|
||||
*/
|
||||
class ChatRoomCacheBuilder implements ICacheBuilder {
|
||||
/**
|
||||
* @see wcf\system\cache\ICacheBuilder::getData()
|
||||
* @see \wcf\system\cache\ICacheBuilder::getData()
|
||||
*/
|
||||
public function getData(array $cacheResource) {
|
||||
// get all chat rooms
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace wcf\system\chat\permissions;
|
||||
namespace wcf\system\chat\permission;
|
||||
use \wcf\system\acl\ACLHandler;
|
||||
use \wcf\system\cache\CacheHandler;
|
||||
use \wcf\system\package\PackageDependencyHandler;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
@ -15,14 +16,25 @@ use \wcf\system\WCF;
|
||||
*/
|
||||
class ChatPermissionHandler extends \wcf\system\SingletonFactory {
|
||||
protected $chatPermissions = array();
|
||||
protected static $defaults = array(
|
||||
'user.canEnter' => true,
|
||||
'user.canWrite' => true,
|
||||
'mod.canAlwaysEnter' => false,
|
||||
'mod.canAlwaysWrite' => false
|
||||
);
|
||||
|
||||
/**
|
||||
* @see wcf\system\SingletonFactory::init()
|
||||
* @see \wcf\system\SingletonFactory::init()
|
||||
*/
|
||||
protected function init() {
|
||||
$packageID = PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
|
||||
$ush = \wcf\system\user\storage\UserStorageHandler::getInstance();
|
||||
// TODO: get groups permissions
|
||||
|
||||
// get groups permissions
|
||||
$groups = implode(',', WCF::getUser()->getGroupIDs());
|
||||
$groupsFileName = \wcf\util\StringUtil::getHash(implode('-', WCF::getUser()->getGroupIDs()));
|
||||
CacheHandler::getInstance()->addResource('chatPermission-'.$groups, WCF_DIR.'cache/cache.chatPermission-'.$groupsFileName.'.php', 'wcf\system\cache\builder\ChatPermissionCacheBuilder');
|
||||
$this->chatPermissions = CacheHandler::getInstance()->get('chatPermission-'.$groups);
|
||||
|
||||
// get user permissions
|
||||
if (WCF::getUser()->userID) {
|
||||
@ -75,7 +87,20 @@ class ChatPermissionHandler extends \wcf\system\SingletonFactory {
|
||||
* @return boolean
|
||||
*/
|
||||
public function getPermission(\wcf\data\chat\room\ChatRoom $room, $permission) {
|
||||
if (!isset($this->chatPermissions[$room->roomID][$permission])) return true;
|
||||
if (!isset($this->chatPermissions[$room->roomID][$permission])) {
|
||||
return isset(self::$defaults[$permission]) ? self::$defaults[$permission] : false;
|
||||
}
|
||||
return (boolean) $this->chatPermissions[$room->roomID][$permission];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache.
|
||||
*/
|
||||
public static function clearCache() {
|
||||
$packageID = PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
|
||||
$ush = \wcf\system\user\storage\UserStorageHandler::getInstance();
|
||||
|
||||
$ush->resetAll('chatUserPermissions', $packageID);
|
||||
\wcf\system\cache\CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.chatPermission-[a-f0-9]{40}.php');
|
||||
}
|
||||
}
|
@ -8,17 +8,17 @@ namespace wcf\system\event\listener;
|
||||
* @copyright 2010-2012 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package timwolla.wcf.chat
|
||||
* @subpackage system.event.listener
|
||||
* @subpackage system.event.listener
|
||||
*/
|
||||
class ChatRouteListener implements \wcf\system\event\IEventListener {
|
||||
/**
|
||||
* @see wcf\system\event\IEventListener::execute()
|
||||
* @see \wcf\system\event\IEventListener::execute()
|
||||
*/
|
||||
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|Copyright)');
|
||||
$route->setParameterOption('action', null, '(Message|Log|Send|RefreshRoomList|Copyright|Leave)');
|
||||
$eventObj->addRoute($route);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class ChatPageMenuItemProvider extends DefaultPageMenuItemProvider {
|
||||
/**
|
||||
* Hides the button when there is no valid room
|
||||
*
|
||||
* @see \wcf\system\menu\page\PageMenuItemProvider::isVisible()
|
||||
* @see \wcf\system\menu\page\PageMenuItemProvider::isVisible()
|
||||
*/
|
||||
public function isVisible() {
|
||||
// guests are not supported
|
||||
@ -43,7 +43,7 @@ class ChatPageMenuItemProvider extends DefaultPageMenuItemProvider {
|
||||
/**
|
||||
* Modifies the link to show the Link we would be redirect to.
|
||||
*
|
||||
* @see \wcf\system\menu\page\PageMenuItemProvider::getLink()
|
||||
* @see \wcf\system\menu\page\PageMenuItemProvider::getLink()
|
||||
*/
|
||||
public function getLink() {
|
||||
return \wcf\system\request\LinkHandler::getInstance()->getLink('Chat', array(
|
||||
|
@ -12,14 +12,14 @@ namespace wcf\system\option;
|
||||
*/
|
||||
class TimeIntervalOptionType extends TextOptionType {
|
||||
/**
|
||||
* @see wcf\system\option\IOptionType::getData()
|
||||
* @see \wcf\system\option\IOptionType::getData()
|
||||
*/
|
||||
public function getData(\wcf\data\option\Option $option, $newValue) {
|
||||
return \wcf\util\ChatUtil::timeModifier($newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see wcf\system\option\TextOptionType::getFormElement()
|
||||
* @see \wcf\system\option\TextOptionType::getFormElement()
|
||||
*/
|
||||
public function getFormElement(\wcf\data\option\Option $option, $value) {
|
||||
$tmp = (int) ($value / 60);
|
||||
|
@ -67,7 +67,7 @@ class ChatUtil {
|
||||
if ($data[WCF::getUser()->userID] === null) {
|
||||
switch ($field) {
|
||||
case 'color':
|
||||
$data[WCF::getUser()->userID] = array(1 => 0xFF0000, 2 => 0x00FF00);
|
||||
$data[WCF::getUser()->userID] = array(1 => self::getRandomNumber(), 2 => self::getRandomNumber() * 0xFFFF);
|
||||
break;
|
||||
}
|
||||
static::writeUserData(array($field => $data[WCF::getUser()->userID]));
|
||||
@ -79,6 +79,16 @@ class ChatUtil {
|
||||
else return $data[WCF::getUser()->userID];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random number.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function /* int */ getRandomNumber() {
|
||||
return 4; // chosen by a fair dice roll
|
||||
// guaranteed to be random
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes user data
|
||||
*
|
||||
|
@ -11,7 +11,7 @@
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
.wcf-sidebar {
|
||||
margin-bottom: -20px !important;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
@ -32,7 +32,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatTopic, #smileyList, #timsChatOptions {
|
||||
#timsChatTopic, #smileyList {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
padding-left: 7px !important;
|
||||
}
|
||||
|
||||
#smileyList .smilies, .smallButtons {
|
||||
#smileyList .smilies {
|
||||
li {
|
||||
display: inline;
|
||||
margin: 5px 5px 0 0;
|
||||
@ -63,7 +63,9 @@
|
||||
}
|
||||
|
||||
#timsChatOptions {
|
||||
display: inline-block;
|
||||
> ul {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatUserList {
|
||||
@ -100,7 +102,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.unloaded {
|
||||
&.unloaded {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
@ -178,7 +180,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.active .badge {
|
||||
&.active .wcf-badge {
|
||||
font-size: 65% !important;
|
||||
color: #fff;
|
||||
background-color: #369;
|
||||
|
69
install.sql
69
install.sql
@ -1,46 +1,47 @@
|
||||
DROP TABLE IF EXISTS wcf1_chat_message;
|
||||
CREATE TABLE wcf1_chat_message (
|
||||
messageID int(10) NOT NULL AUTO_INCREMENT,
|
||||
roomID int(10) NOT NULL,
|
||||
sender int(10) DEFAULT NULL,
|
||||
username varchar(255) DEFAULT NULL,
|
||||
receiver int(10) DEFAULT NULL,
|
||||
time int(10) NOT NULL,
|
||||
type tinyint(3) NOT NULL DEFAULT 1,
|
||||
message mediumtext NOT NULL,
|
||||
enableSmilies tinyint(1) NOT NULL DEFAULT 1,
|
||||
enableHTML tinyint(1) NOT NULL DEFAULT 0,
|
||||
color1 int(10) NOT NULL DEFAULT 0,
|
||||
color2 int(10) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (messageID),
|
||||
KEY roomID (roomID),
|
||||
KEY sender (sender),
|
||||
KEY receiver (receiver)
|
||||
messageID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
roomID INT(10) NOT NULL,
|
||||
sender INT(10) DEFAULT NULL,
|
||||
username VARCHAR(255) DEFAULT NULL,
|
||||
receiver INT(10) DEFAULT NULL,
|
||||
time INT(10) NOT NULL,
|
||||
type TINYINT(3) NOT NULL DEFAULT 1,
|
||||
message MEDIUMTEXT NOT NULL,
|
||||
enableSmilies TINYINT(1) NOT NULL DEFAULT 1,
|
||||
enableHTML TINYINT(1) NOT NULL DEFAULT 0,
|
||||
color1 INT(10) NOT NULL DEFAULT 0,
|
||||
color2 INT(10) NOT NULL DEFAULT 0,
|
||||
|
||||
KEY roomID (roomID),
|
||||
KEY sender (sender),
|
||||
KEY receiver (receiver)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS wcf1_chat_room;
|
||||
CREATE TABLE wcf1_chat_room (
|
||||
roomID int(10) NOT NULL AUTO_INCREMENT,
|
||||
title varchar(25) NOT NULL,
|
||||
topic varchar(255) NOT NULL,
|
||||
position int(10) NOT NULL DEFAULT 0,
|
||||
permanent tinyint(1) NOT NULL DEFAULT 1,
|
||||
owner int(10) DEFAULT NULL,
|
||||
PRIMARY KEY (roomID),
|
||||
KEY positionKey (position),
|
||||
KEY owner (owner)
|
||||
roomID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
topic VARCHAR(255) NOT NULL,
|
||||
position INT(10) NOT NULL DEFAULT 0,
|
||||
permanent TINYINT(1) NOT NULL DEFAULT 1,
|
||||
owner INT(10) DEFAULT NULL,
|
||||
|
||||
KEY positionKey (position),
|
||||
KEY owner (owner)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS wcf1_chat_room_suspension;
|
||||
CREATE TABLE wcf1_chat_room_suspension (
|
||||
roomID int(10) NOT NULL,
|
||||
userID int(10) NOT NULL,
|
||||
type tinyint(3) NOT NULL,
|
||||
time int(10) NOT NULL,
|
||||
PRIMARY KEY (roomID, userID),
|
||||
KEY userID (userID),
|
||||
KEY type (type, time),
|
||||
KEY time (time)
|
||||
userID INT(10) NOT NULL,
|
||||
roomID INT(10) DEFAULT NULL,
|
||||
type TINYINT(3) NOT NULL,
|
||||
time INT(10) NOT NULL,
|
||||
|
||||
UNIQUE KEY main (userID, roomID),
|
||||
KEY roomID (roomID),
|
||||
KEY type (type, time),
|
||||
KEY time (time)
|
||||
);
|
||||
|
||||
ALTER TABLE wcf1_chat_message ADD FOREIGN KEY (receiver) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
|
||||
@ -52,7 +53,7 @@ ALTER TABLE wcf1_chat_room ADD FOREIGN KEY (owner) REFERENCES wcf1_user (userID)
|
||||
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;
|
||||
|
||||
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 ('wcf.chat.room.title1', 'wcf.chat.room.topic1', 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);
|
||||
|
@ -1,5 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<language 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/maelstrom/language.xsd" languagecode="de">
|
||||
<category name="wcf.acp.chat">
|
||||
<item name="wcf.acp.chat.room.list"><![CDATA[Chaträume]]></item>
|
||||
<item name="wcf.acp.chat.room.add"><![CDATA[Chatraum hinzufügen]]></item>
|
||||
<item name="wcf.acp.chat.room.edit"><![CDATA[Chatraum bearbeiten]]></item>
|
||||
</category>
|
||||
|
||||
<category name="wcf.acp.menu">
|
||||
<item name="wcf.acp.menu.link.chat"><![CDATA[Chat]]></item>
|
||||
<item name="wcf.acp.menu.link.chat.room.list"><![CDATA[Chaträume auflisten]]></item>
|
||||
<item name="wcf.acp.menu.link.chat.room.add"><![CDATA[Chatraum hinzufügen]]></item>
|
||||
</category>
|
||||
|
||||
<category name="wcf.acp.option">
|
||||
<item name="wcf.acp.option.category.chat"><![CDATA[Chat]]></item>
|
||||
<item name="wcf.acp.option.category.chat.general"><![CDATA[Allgemein]]></item>
|
||||
@ -14,8 +26,8 @@
|
||||
<item name="wcf.acp.option.chat_display_clock.description"><![CDATA[Aktiviert die Anzeige der Uhrzeit von Nachrichten]]></item>
|
||||
<item name="wcf.acp.option.chat_animations"><![CDATA[Animationen aktivieren]]></item>
|
||||
<item name="wcf.acp.option.chat_animations.description"><![CDATA[Aktiviert die Animation neuer Nachrichten.]]></item>
|
||||
<item name="wcf.acp.option.chat_length"><![CDATA[Maximale Textlänge]]></item>
|
||||
<item name="wcf.acp.option.chat_length.description"><![CDATA[Gibt die maximale Länge einer Chatnachricht an.]]></item>
|
||||
<item name="wcf.acp.option.chat_max_length"><![CDATA[Maximale Textlänge]]></item>
|
||||
<item name="wcf.acp.option.chat_max_length.description"><![CDATA[Gibt die maximale Länge einer Chatnachricht an.]]></item>
|
||||
<item name="wcf.acp.option.chat_show_version"><![CDATA[Versionsnummer anzeigen]]></item>
|
||||
<item name="wcf.acp.option.chat_show_version.description"><![CDATA[Zeigt die Versionsnummer im Copyrighthinweis an.]]></item>
|
||||
|
||||
@ -24,11 +36,7 @@
|
||||
<item name="wcf.acp.option.chat_log_archivetime"><![CDATA[Speicherzeit]]></item>
|
||||
<item name="wcf.acp.option.chat_log_archivetime.description"><![CDATA[Gibt die Zeit in Minuten an, die eine Nachricht im Protokoll gespeichert bleibt.]]></item>
|
||||
</category>
|
||||
|
||||
<category name="wcf.header">
|
||||
<item name="wcf.header.menu.chat"><![CDATA[Chat]]></item>
|
||||
</category>
|
||||
|
||||
|
||||
<category name="wcf.chat">
|
||||
<item name="wcf.chat.title"><![CDATA[Chat]]></item>
|
||||
<item name="wcf.chat.protocol"><![CDATA[Protokoll]]></item>
|
||||
@ -55,4 +63,14 @@
|
||||
<!-- 2 = TYPE_LEAVE -->
|
||||
<item name="wcf.chat.message.2"><![CDATA[hat den Chat verlassen.]]></item>
|
||||
</category>
|
||||
|
||||
<!-- I18N Values -->
|
||||
<category name="wcf.chat.room">
|
||||
<item name="wcf.chat.room.title1"><![CDATA[Hauptchat]]></item>
|
||||
<item name="wcf.chat.room.topic1"><![CDATA[Vielen Dank, dass Sie sich für Tims Chat entschieden haben. Bitte besuchen Sie das ACP um diesen Text anzupassen.]]></item>
|
||||
</category>
|
||||
|
||||
<category name="wcf.header">
|
||||
<item name="wcf.header.menu.chat"><![CDATA[Chat]]></item>
|
||||
</category>
|
||||
</language>
|
@ -49,7 +49,7 @@
|
||||
<defaultvalue>1</defaultvalue>
|
||||
<showorder>7</showorder>
|
||||
</option>
|
||||
<option name="chat_length">
|
||||
<option name="chat_max_length">
|
||||
<categoryname>chat.general</categoryname>
|
||||
<optiontype>integer</optiontype>
|
||||
<defaultvalue>500</defaultvalue>
|
||||
|
12
package.xml
12
package.xml
@ -5,7 +5,7 @@
|
||||
<packagedescription><![CDATA[Chat for WoltLab Community Framework™]]></packagedescription>
|
||||
<standalone>0</standalone>
|
||||
<isunique>1</isunique>
|
||||
<version>3.0.0 Alpha 3</version>
|
||||
<version>3.0.0 Alpha 8</version>
|
||||
<date>2011-11-26</date>
|
||||
<plugin>com.woltlab.wcf.bbcode</plugin> <!-- TODO: Correct me -->
|
||||
</packageinformation>
|
||||
@ -19,30 +19,36 @@
|
||||
<requiredpackage minversion="2.0.0 Alpha 1">com.woltlab.wcf</requiredpackage>
|
||||
<requiredpackage minversion="1.0.0 Alpha 1">com.woltlab.wcf.bbcode</requiredpackage>
|
||||
<requiredpackage minversion="1.0.0 Alpha 1">com.woltlab.wcf.acl</requiredpackage>
|
||||
<requiredpackage minversion="1.0.0 Alpha 1">com.woltlab.wcf.message</requiredpackage>
|
||||
</requiredpackages>
|
||||
|
||||
<instructions type="install">
|
||||
<instruction type="language">language/*.xml</instruction>
|
||||
<instruction type="file">file.tar</instruction>
|
||||
<instruction type="template">template.tar</instruction>
|
||||
<instruction type="acpTemplate">acptemplate.tar</instruction>
|
||||
<instruction type="sql">install.sql</instruction>
|
||||
<instruction type="objectType">objectType.xml</instruction>
|
||||
<instruction type="option">option.xml</instruction>
|
||||
<instruction type="pageMenu">pagemenu.xml</instruction>
|
||||
<instruction type="eventListener">eventListener.xml</instruction>
|
||||
<instruction type="templateListener">templatelistener.xml</instruction>
|
||||
<instruction type="aclOption">acloptions.xml</instruction>
|
||||
<instruction type="acpMenu">acpMenu.xml</instruction>
|
||||
<instruction type="userGroupOption">userGroupOption.xml</instruction>
|
||||
</instructions>
|
||||
|
||||
<instructions type="update" fromversion="3.0.0 Alpha *">
|
||||
<instruction type="language">language/*.xml</instruction>
|
||||
<instruction type="file">file.tar</instruction>
|
||||
<instruction type="template">template.tar</instruction>
|
||||
<instruction type="acpTemplate">acptemplate.tar</instruction>
|
||||
<instruction type="objectType">objectType.xml</instruction>
|
||||
<instruction type="option">option.xml</instruction>
|
||||
<instruction type="pageMenu">pagemenu.xml</instruction>
|
||||
<instruction type="eventListener">eventListener.xml</instruction>
|
||||
<instruction type="templateListener">templatelistener.xml</instruction>
|
||||
<instruction type="aclOption">acloptions.xml</instruction>
|
||||
<instruction type="acpMenu">acpMenu.xml</instruction>
|
||||
<instruction type="userGroupOption">userGroupOption.xml</instruction>
|
||||
<instruction type="script">acp/timwolla.wcf.chat.update.php</instruction>
|
||||
</instructions>
|
||||
</package>
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
{include file='headInclude' sandbox=false}
|
||||
<style type="text/css">
|
||||
@import url("{@RELATIVE_WCF_DIR}style/timwolla.wcf.chat.css");
|
||||
@import url("{@$__wcf->getPath('wcf')}style/timwolla.wcf.chat.css");
|
||||
#timsChatCopyrightDialog {
|
||||
background-image: url("{link controller='Chat' action='Copyright' sheep=1}{/link}");
|
||||
background-position: right 45px;
|
||||
@ -56,6 +56,7 @@
|
||||
|
||||
.jsCounterInput {
|
||||
height: 16px;
|
||||
box-sizing: content-box !important;
|
||||
}
|
||||
|
||||
.jsCounterInput, .jsCounter {
|
||||
@ -89,103 +90,63 @@
|
||||
</head>
|
||||
|
||||
<body id="tpl{$templateName|ucfirst}">
|
||||
{capture assign='sidebar'}
|
||||
<div id="sidebarContent" class="sidebarContent">
|
||||
<nav class="timsChatSidebarTabs">
|
||||
<ul>
|
||||
<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} <span class="badge">{#$rooms|count}</span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div id="sidebarContainer">
|
||||
<ul id="timsChatUserList">
|
||||
{*section name=user start=1 loop=26}
|
||||
<li class="timsChatUser">
|
||||
<a href="javascript:;">User {$user}</a>
|
||||
<ul class="timsChatUserMenu">
|
||||
<li>
|
||||
<a href="javascript:;">{lang}wcf.chat.query{/lang}</a>
|
||||
<a href="javascript:;">{lang}wcf.chat.kick{/lang}</a>
|
||||
<a href="javascript:;">{lang}wcf.chat.ban{/lang}</a>
|
||||
<a href="{link controller="User" id=$user}{/link}">{lang}wcf.chat.profile{/lang}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{/section*}
|
||||
</ul>
|
||||
<nav id="timsChatRoomList" class="sidebarMenu" style="display: none;">
|
||||
<div>
|
||||
<ul>
|
||||
{foreach from=$rooms item='roomListRoom'}
|
||||
{if $roomListRoom->canEnter()}
|
||||
<li{if $roomListRoom->roomID == $room->roomID} class="activeMenuItem"{/if}>
|
||||
<a href="{link controller='Chat' object=$roomListRoom}{/link}" class="timsChatRoom">{$roomListRoom}</a>
|
||||
</li>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</ul>
|
||||
<div style="text-align: center;"><button type="button">Force Refresh</button></div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
{/capture}
|
||||
{capture assign='sidebar'}{include file='chatSidebar'}{/capture}
|
||||
{capture assign='headerNavigation'}{include file='chatNavigationInclude'}{/capture}
|
||||
{include file='header' sandbox=false sidebarOrientation='right'}
|
||||
|
||||
<div id="timsChatRoomContent">
|
||||
<div id="timsChatTopic" class="border"{if $room->topic|language === ''} style="display: none;"{/if}>{$room->topic|language}</div>
|
||||
<div class="timsChatMessageContainer border content">
|
||||
<div id="timsChatTopic" class="wcf-border"{if $room->topic|language === ''} style="display: none;"{/if}>{$room->topic|language}</div>
|
||||
<div class="timsChatMessageContainer wcf-border wcf-content">
|
||||
<ul>
|
||||
<noscript><li class="error">{lang}wcf.chat.noJs{/lang}</li></noscript>
|
||||
<noscript><li class="wcf-error">{lang}wcf.chat.noJs{/lang}</li></noscript>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form id="timsChatForm" action="{link controller="Chat" action="Send"}{/link}" method="post">
|
||||
<input type="text" id="timsChatInput" class="inputText long jsCounterInput" name="text" autocomplete="off" maxlength="{CHAT_LENGTH}" disabled="disabled" required="required" placeholder="{lang}wcf.chat.submit.default{/lang}" />
|
||||
<input type="text" id="timsChatInput" class="inputText long jsCounterInput" name="text" autocomplete="off" maxlength="{@CHAT_MAX_LENGTH}" disabled="disabled" required="required" placeholder="{lang}wcf.chat.submit.default{/lang}" />
|
||||
</form>
|
||||
|
||||
<div id="timsChatControls">
|
||||
<div id="smileyList" class="border">
|
||||
<ul class="smilies">
|
||||
{foreach from=$smilies item='smiley'}
|
||||
<li>
|
||||
<img src="{$smiley->getURL()}" alt="{$smiley->smileyCode}" title="{$smiley->smileyCode}" class="smiley" />
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
<div id="timsChatOptions" class="border">
|
||||
<div class="smallButtons">
|
||||
<ul>
|
||||
<li>
|
||||
<a id="timsChatAutoscroll" href="javascript:;" class="timsChatToggle balloonTooltip" title="{lang}wcf.global.button.disable{/lang}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}" data-status="1">
|
||||
<img alt="" src="{icon size='S'}enabled1{/icon}" /> <span>{lang}wcf.chat.scroll{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatNotify" href="javascript:;" class="timsChatToggle balloonTooltip" title="{lang}wcf.global.button.enable{/lang}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}" data-status="0">
|
||||
<img alt="" src="{icon size='S'}disabled1{/icon}" /> <span>{lang}wcf.chat.notify{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatSmilies" href="javascript:;" class="timsChatToggle balloonTooltip" title="{lang}wcf.global.button.disable{/lang}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}" data-status="1">
|
||||
<img alt="" src="{icon size='S'}enabled1{/icon}" /> <span>{lang}wcf.chat.smilies{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatClear" href="javascript:;" class="balloonTooltip" title="{lang}wcf.chat.clear.description{/lang}">
|
||||
<img alt="" src="{icon size='S'}delete1{/icon}" /> <span>{lang}wcf.chat.clear{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatMark" href="javascript:;" class="balloonTooltip" title="{lang}wcf.chat.mark.description{/lang}">
|
||||
<img alt="" src="{icon size='S'}check1{/icon}" /> <span>{lang}wcf.chat.mark{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<div id="timsChatControls" class="wcf-border">
|
||||
{if MODULE_SMILEY}
|
||||
<div id="smileyList">
|
||||
<ul class="smilies">
|
||||
{foreach from=$smilies item='smiley'}
|
||||
<li>
|
||||
<img src="{$smiley->getURL()}" alt="{$smiley->smileyCode}" title="{$smiley->smileyTitle}" class="jsSmiley jsTooltip" />
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<nav id="timsChatOptions">
|
||||
<ul class="wcf-smallButtons">
|
||||
<li>
|
||||
<a id="timsChatAutoscroll" href="javascript:;" class="timsChatToggle jsTooltip wcf-button" title="{lang}wcf.global.button.disable{/lang}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}" data-status="1">
|
||||
<img alt="" src="{icon size='S'}enabled1{/icon}" /> <span>{lang}wcf.chat.scroll{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatNotify" href="javascript:;" class="timsChatToggle jsTooltip wcf-button" title="{lang}wcf.global.button.enable{/lang}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}" data-status="0">
|
||||
<img alt="" src="{icon size='S'}disabled1{/icon}" /> <span>{lang}wcf.chat.notify{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{if !MODULE_SMILEY} style="display: none;"{/if}>
|
||||
<a id="timsChatSmilies" href="javascript:;" class="timsChatToggle jsTooltip wcf-button" title="{lang}wcf.global.button.disable{/lang}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}" data-status="1">
|
||||
<img alt="" src="{icon size='S'}enabled1{/icon}" /> <span>{lang}wcf.chat.smilies{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatClear" href="javascript:;" class="jsTooltip wcf-button" title="{lang}wcf.chat.clear.description{/lang}">
|
||||
<img alt="" src="{icon size='S'}delete1{/icon}" /> <span>{lang}wcf.chat.clear{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatMark" href="javascript:;" class="jsTooltip wcf-button" title="{lang}wcf.chat.mark.description{/lang}">
|
||||
<img alt="" src="{icon size='S'}check1{/icon}" /> <span>{lang}wcf.chat.mark{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{include file='chatCopyright'}
|
||||
</div>
|
||||
</div>
|
||||
@ -201,8 +162,7 @@
|
||||
// populate config
|
||||
TimWolla.WCF.Chat.config = {
|
||||
reloadTime: {@CHAT_RELOADTIME},
|
||||
animations: {@CHAT_ANIMATIONS},
|
||||
maxTextLength: {@CHAT_LENGTH}
|
||||
unloadURL: '{link controller='Chat' action='Leave'}{/link}'
|
||||
}
|
||||
WCF.Language.addObject({
|
||||
'wcf.chat.query': '{lang}wcf.chat.query{/lang}',
|
||||
|
@ -1,2 +1,2 @@
|
||||
<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/TimWolla.WCF.Chat.js{if $chatVersion|isset}?version={$chatVersion|urlencode}{/if}"></script>
|
||||
<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/jCounter.jQuery.js"></script>
|
||||
<script type="text/javascript" src="{@$__wcf->getPath('wcf')}js/TimWolla.WCF.Chat.js{if $chatVersion|isset}?version={$chatVersion|urlencode}{/if}"></script>
|
||||
<script type="text/javascript" src="{@$__wcf->getPath('wcf')}js/jCounter.jQuery.js"></script>
|
@ -1 +1 @@
|
||||
{literal}<dl style="margin: 0;"><dt style="width: 145px; margin: 0;"><time style="float: left;">{@$formattedTime}</time> {@$formattedUsername}{$separator}</dt> <dd style="padding: 0; margin-left: 150px;">{@$formattedMessage}</dd></dl>{/literal}
|
||||
<dl style="margin: 0;"><dt style="width: 145px; margin: 0;">{if CHAT_DISPLAY_CLOCK}<time style="float: left;">{ldelim}@$formattedTime}</time> {/if}{literal}{@$formattedUsername}{$separator}</dt> <dd style="padding: 0; margin-left: 150px;">{@$formattedMessage}</dd></dl>{/literal}
|
@ -1,4 +1,5 @@
|
||||
{if $templateName == 'chat'}
|
||||
<li><a href="{link controller="Chat" action="Log"}{/link}" title="{lang}wcf.chat.protocol{/lang}" class="balloonTooltip"><img src="{icon size='S'}session1{/icon}" alt="" /> <span>{lang}wcf.chat.protocol{/lang}</span></a></li>
|
||||
<li><a href="{link controller="Chat"}{/link}" title="{lang}wcf.chat.title{/lang}" class="balloonTooltip"><img src="{icon size='S'}chat1{/icon}" alt="" /> <span>{lang}wcf.chat.title{/lang}</span></a></li>
|
||||
{/if}
|
||||
<li>
|
||||
<a href="{link controller="Chat" action="Log"}{/link}" title="{lang}wcf.chat.protocol{/lang}" class="jsTooltip">
|
||||
<img src="{icon size='S'}session1{/icon}" alt="" /> <span>{lang}wcf.chat.protocol{/lang}</span>
|
||||
</a>
|
||||
</li>
|
27
template/chatSidebar.tpl
Normal file
27
template/chatSidebar.tpl
Normal file
@ -0,0 +1,27 @@
|
||||
<div id="sidebarContent" class="wcf-sidebarContent">
|
||||
<nav class="timsChatSidebarTabs">
|
||||
<ul>
|
||||
<li id="toggleUsers" class="active"><a href="javascript:;" title="{lang}wcf.chat.users{/lang}">{lang}wcf.chat.users{/lang} <span class="wcf-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} <span class="wcf-badge">{#$rooms|count}</span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div id="sidebarContainer">
|
||||
<ul id="timsChatUserList">
|
||||
</ul>
|
||||
<nav id="timsChatRoomList" class="wcf-sidebarMenu" style="display: none;">
|
||||
<div>
|
||||
<ul>
|
||||
{foreach from=$rooms item='roomListRoom'}
|
||||
{if $roomListRoom->canEnter()}
|
||||
<li{if $roomListRoom->roomID == $room->roomID} class="activeMenuItem"{/if}>
|
||||
<a href="{link controller='Chat' object=$roomListRoom}{/link}" class="timsChatRoom">{$roomListRoom}</a>
|
||||
</li>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</ul>
|
||||
<div style="text-align: center;"><button type="button">{lang}wcf.chat.forceRefresh{/lang}</button></div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
@ -1,11 +0,0 @@
|
||||
<?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/templatelistener.xsd">
|
||||
<import>
|
||||
<templatelistener name="chatHeaderNavigation">
|
||||
<environment>user</environment>
|
||||
<templatename>header</templatename>
|
||||
<eventname>headerNavigation</eventname>
|
||||
<templatecode><![CDATA[{include file='chatNavigationInclude'}]]></templatecode>
|
||||
</templatelistener>
|
||||
</import>
|
||||
</data>
|
31
userGroupOption.xml
Normal file
31
userGroupOption.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?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/maelstrom/userGroupOption.xsd">
|
||||
<import>
|
||||
<categories>
|
||||
<category name="admin.content.chat">
|
||||
<parent>admin.content</parent>
|
||||
</category>
|
||||
</categories>
|
||||
|
||||
<options>
|
||||
<option name="admin.content.chat.canAddRoom">
|
||||
<categoryname>admin.content.chat</categoryname>
|
||||
<optiontype>boolean</optiontype>
|
||||
<defaultvalue>0</defaultvalue>
|
||||
<admindefaultvalue>1</admindefaultvalue>
|
||||
</option>
|
||||
<option name="admin.content.chat.canEditRoom">
|
||||
<categoryname>admin.content.chat</categoryname>
|
||||
<optiontype>boolean</optiontype>
|
||||
<defaultvalue>0</defaultvalue>
|
||||
<admindefaultvalue>1</admindefaultvalue>
|
||||
</option>
|
||||
<option name="admin.content.chat.canDeleteRoom">
|
||||
<categoryname>admin.content.chat</categoryname>
|
||||
<optiontype>boolean</optiontype>
|
||||
<defaultvalue>0</defaultvalue>
|
||||
<admindefaultvalue>1</admindefaultvalue>
|
||||
</option>
|
||||
</options>
|
||||
</import>
|
||||
</data>
|
Loading…
x
Reference in New Issue
Block a user