mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2024-10-31 14:10:08 +00:00
Merge branch 'master' into protocol
Conflicts: acpMenu.xml
This commit is contained in:
commit
db8fa89e7b
@ -1,5 +1,6 @@
|
|||||||
language: php
|
language: php
|
||||||
php:
|
php:
|
||||||
|
- 5.5
|
||||||
- 5.4
|
- 5.4
|
||||||
- 5.3
|
- 5.3
|
||||||
before_install:
|
before_install:
|
||||||
|
@ -23,6 +23,13 @@
|
|||||||
<showorder>2</showorder>
|
<showorder>2</showorder>
|
||||||
</acpmenuitem>
|
</acpmenuitem>
|
||||||
|
|
||||||
|
<acpmenuitem name="chat.acp.menu.link.suspension.list">
|
||||||
|
<controller><![CDATA[chat\acp\page\ChatSuspensionListPage]]></controller>
|
||||||
|
<parent>chat.acp.menu.link.chat</parent>
|
||||||
|
<permissions>admin.chat.canManageSuspensions</permissions>
|
||||||
|
<showorder>3</showorder>
|
||||||
|
</acpmenuitem>
|
||||||
|
|
||||||
<acpmenuitem name="chat.acp.menu.link.log">
|
<acpmenuitem name="chat.acp.menu.link.log">
|
||||||
<controller><![CDATA[chat\acp\page\MessageLogListPage]]></controller>
|
<controller><![CDATA[chat\acp\page\MessageLogListPage]]></controller>
|
||||||
<parent>chat.acp.menu.link.chat</parent>
|
<parent>chat.acp.menu.link.chat</parent>
|
||||||
|
167
acptemplate/chatSuspensionList.tpl
Normal file
167
acptemplate/chatSuspensionList.tpl
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
{include file='header' pageTitle='chat.acp.suspension.list'}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
//<![CDATA[
|
||||||
|
$(function() {
|
||||||
|
new WCF.Search.User('#username', null, false, [ ], false);
|
||||||
|
new WCF.Search.User('#issuerUsername', null, false, [ ], false);
|
||||||
|
|
||||||
|
var proxy = new WCF.Action.Proxy({
|
||||||
|
success: function (data, textStatus, jqXHR) {
|
||||||
|
$('.jsSuspensionRow').each(function(index, row) {
|
||||||
|
var row = $(row);
|
||||||
|
if (WCF.inArray(row.data('objectID'), data.objectIDs)) {
|
||||||
|
row.find('.jsRevokeButton').addClass('disabled').removeClass('pointer').off('click');
|
||||||
|
|
||||||
|
(new WCF.System.Notification('{"chat.acp.suspension.revoke.success"|language|encodeJS}')).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('.jsRevokeButton:not(.disabled)').click(function () {
|
||||||
|
var objectID = $(this).parents('.jsSuspensionRow').data('objectID');
|
||||||
|
|
||||||
|
WCF.System.Confirmation.show($(this).data('confirmMessage'), $.proxy(function (action) {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
proxy.setOption('data', {
|
||||||
|
actionName: 'revoke',
|
||||||
|
className: '\\chat\\data\\suspension\\SuspensionAction',
|
||||||
|
objectIDs: [ objectID ]
|
||||||
|
});
|
||||||
|
proxy.sendRequest();
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="boxHeadline">
|
||||||
|
<h1>{lang}chat.acp.suspension.list{/lang}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form method="post" action="{link controller='ChatSuspensionList' application='chat'}{/link}">
|
||||||
|
<div class="container containerPadding marginTop">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{lang}wcf.global.filter{/lang}</legend>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dd>
|
||||||
|
<label><input type="checkbox" id="displayRevoked" name="displayRevoked" value="1"{if $displayRevoked} checked="checked"{/if} /> {lang}chat.acp.suspension.displayRevoked{/lang}</label>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input type="text" id="username" name="username" class="medium" value="{$username}" />
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="issuerUsername">{lang}chat.acp.suspension.issuer{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<input type="text" id="issuerUsername" name="issuerUsername" class="medium" value="{$issuerUsername}" />
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="roomID">{lang}chat.general.room{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<select id="roomID" name="roomID">
|
||||||
|
<option value="-1"{if $roomID == -1} selected="selected"{/if}></option>
|
||||||
|
<option value="0"{if $roomID == 0} selected="selected"{/if}>{lang}chat.room.global{/lang}</option>
|
||||||
|
<option value="" disabled="disabled">-------------</option>
|
||||||
|
{foreach from=$availableRooms key=id item=room}
|
||||||
|
<option value="{$id}" {if $roomID == $id}selected="selected"{/if}>{$room}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><label for="suspensionType">{lang}chat.acp.suspension.type{/lang}</label></dt>
|
||||||
|
<dd>
|
||||||
|
<select id="suspensionType" name="suspensionType">
|
||||||
|
<option value=""{if $suspensionType == null} selected="selected"{/if}></option>
|
||||||
|
<option value="{'\chat\data\suspension\Suspension::TYPE_MUTE'|constant}"{if $suspensionType == '\chat\data\suspension\Suspension::TYPE_MUTE'|constant} selected="selected"{/if}>{lang}chat.suspension.{'\chat\data\suspension\Suspension::TYPE_MUTE'|constant}{/lang}</option>
|
||||||
|
<option value="{'\chat\data\suspension\Suspension::TYPE_BAN'|constant}"{if $suspensionType == '\chat\data\suspension\Suspension::TYPE_BAN'|constant} selected="selected"{/if}>{lang}chat.suspension.{'\chat\data\suspension\Suspension::TYPE_BAN'|constant}{/lang}</option>
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="formSubmit">
|
||||||
|
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{if $objects|count}
|
||||||
|
{capture assign=additionalParameters}{*
|
||||||
|
*}{if $userID}&userID={$userID}{/if}{*
|
||||||
|
*}{if $issuerUserID}&issuerUserID={$issuerUserID}{/if}{*
|
||||||
|
*}{if $roomID}&roomID={$roomID}{/if}{*
|
||||||
|
*}{if $suspensionType}&suspensionType={$suspensionType}{/if}{*
|
||||||
|
*}{if $displayRevoked}&displayRevoked={$displayRevoked}{/if}{*
|
||||||
|
*}{/capture}
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
{pages print=true assign=pagesLinks application="chat" controller="ChatSuspensionList" link="pageNo=%d$additionalParameters"}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tabularBox tabularBoxTitle marginTop">
|
||||||
|
<header>
|
||||||
|
<h2>{lang}chat.acp.suspension.list{/lang} <span class="badge badgeInverse">{#$items}</span></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="columnID{if $sortField == 'suspensionID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=suspensionID&sortOrder={if $sortField == 'suspensionID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
|
||||||
|
<th class="columnUsername{if $sortField == 'username'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=username&sortOrder={if $sortField == 'username' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}wcf.user.username{/lang}</a></th>
|
||||||
|
<th class="columnRoomID{if $sortField == 'roomID'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=roomID&sortOrder={if $sortField == 'roomID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.general.room{/lang}</a></th>
|
||||||
|
<th class="columnSuspensionType{if $sortField == 'type'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=type&sortOrder={if $sortField == 'type' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.type{/lang}</a></th>
|
||||||
|
<th class="columnTime{if $sortField == 'time'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=time&sortOrder={if $sortField == 'time' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.general.time{/lang}</a></th>
|
||||||
|
<th class="columnExpires{if $sortField == 'expires'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=expires&sortOrder={if $sortField == 'expires' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.general.expires{/lang}</a></th>
|
||||||
|
<th class="columnIssuer{if $sortField == 'issuer'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=issuer&sortOrder={if $sortField == 'issuer' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.issuer{/lang}</a></th>
|
||||||
|
<th class="columnMessage{if $sortField == 'reason'} active {@$sortOrder}{/if}"><a href="{link application='chat' controller='ChatSuspensionList'}pageNo={@$pageNo}&sortField=reason&sortOrder={if $sortField == 'reason' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$additionalParameters}{/link}">{lang}chat.acp.suspension.reason{/lang}</a></th>
|
||||||
|
|
||||||
|
{event name='columnHeads'}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{foreach from=$objects item=$suspension}
|
||||||
|
<tr class="jsSuspensionRow" data-object-id="{$suspension->suspensionID}">
|
||||||
|
<td class="columnIcon">
|
||||||
|
<span class="icon icon16 icon-undo{if $suspension->expires <= TIME_NOW} disabled{else} pointer{/if} jsRevokeButton" title="{lang}chat.acp.suspension.revoked{/lang}" data-confirm-message="{lang}chat.acp.suspension.revoke.sure{/lang}"></span>
|
||||||
|
{event name='rowButtons'}
|
||||||
|
</td>
|
||||||
|
<td id="columnID">{#$suspension->suspensionID}</td>
|
||||||
|
<td id="columnUsername"><a href="{link application='chat' controller='ChatSuspensionList'}userID={$suspension->userID}{/link}">{$suspension->username}</a></td>
|
||||||
|
<td id="columnRoomID"><a href="{link application='chat' controller='ChatSuspensionList'}roomID={if $suspension->roomID}{$suspension->roomID}{else}0{/if}{/link}">{if $suspension->roomID}{$suspension->roomTitle|language}{else}{lang}chat.room.global{/lang}{/if}</a></td>
|
||||||
|
<td id="columnSuspensionType"><a href="{link application='chat' controller='ChatSuspensionList'}suspensionType={$suspension->type}{/link}">{lang}chat.suspension.{@$suspension->type}{/lang}</a></td>
|
||||||
|
<td id="columnTime">{$suspension->time|plainTime}</td>
|
||||||
|
<td id="columnExpires">
|
||||||
|
<p>{$suspension->expires|plainTime}{if $suspension->expires > TIME_NOW} ({$suspension->expires|dateDiff}){/if}</p>
|
||||||
|
{if $suspension->revoker && $suspension->expires <= TIME_NOW}<p><small>{lang}chat.acp.suspension.revokedBy{/lang}</small></p>{/if}
|
||||||
|
</td>
|
||||||
|
<td id="columnIssuer"><a href="{link application='chat' controller='ChatSuspensionList'}issuerUserID={$suspension->issuer}{/link}">{$suspension->issuerUsername}</a></td>
|
||||||
|
<td id="columnMessage"{if $suspension->reason != $suspension->reason|truncate:30} class="jsTooltip" title="{$suspension->reason}"{/if}>{$suspension->reason|truncate:30}</a></td>
|
||||||
|
{event name='columns'}
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contentNavigation">
|
||||||
|
{@$pagesLinks}
|
||||||
|
</div>
|
||||||
|
{else}
|
||||||
|
<p class="info">{lang}wcf.global.noItems{/lang}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
{include file='footer'}
|
@ -1,7 +1,7 @@
|
|||||||
{include file='header' pageTitle='chat.acp.room.'|concat:$action}
|
{include file='header' pageTitle='chat.acp.room.'|concat:$action}
|
||||||
|
|
||||||
<script type="text/javascript" src="{@$__wcf->getPath('wcf')}js/WCF.ACL.js"></script>
|
<script src="{@$__wcf->getPath('wcf')}js/WCF.ACL.js"></script>
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
$(function() {
|
$(function() {
|
||||||
new WCF.ACL.List($('#groupPermissions'), {@$objectTypeID}, ''{if $roomID|isset}, {@$roomID}{/if});
|
new WCF.ACL.List($('#groupPermissions'), {@$objectTypeID}, ''{if $roomID|isset}, {@$roomID}{/if});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{include file='header' pageTitle='chat.acp.room.list'}
|
{include file='header' pageTitle='chat.acp.room.list'}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
$(function() {
|
$(function() {
|
||||||
new WCF.Action.Delete('\\chat\\data\\room\\RoomAction', $('.chatRoomRow'));
|
new WCF.Action.Delete('\\chat\\data\\room\\RoomAction', $('.chatRoomRow'));
|
||||||
|
@ -33,7 +33,16 @@ exposed by a function if necessary.
|
|||||||
newMessageCount = 0
|
newMessageCount = 0
|
||||||
scrollUpNotifications = off
|
scrollUpNotifications = off
|
||||||
chatSession = Date.now()
|
chatSession = Date.now()
|
||||||
|
userList =
|
||||||
|
current: {}
|
||||||
|
allTime: {}
|
||||||
|
currentRoom = {}
|
||||||
|
|
||||||
errorVisible = false
|
errorVisible = false
|
||||||
|
inputErrorHidingTimer = null
|
||||||
|
|
||||||
|
lastMessage = null
|
||||||
|
openChannel = 0
|
||||||
|
|
||||||
remainingFailures = 3
|
remainingFailures = 3
|
||||||
|
|
||||||
@ -106,21 +115,29 @@ Make the user leave the chat when **Tims Chat** is about to be unloaded.
|
|||||||
Insert the appropriate smiley code into the input when a smiley is clicked.
|
Insert the appropriate smiley code into the input when a smiley is clicked.
|
||||||
|
|
||||||
$('#smilies').on 'click', 'img', ->
|
$('#smilies').on 'click', 'img', ->
|
||||||
insertText ' ' + $(@).attr('alt') + ' '
|
insertText " #{$(@).attr('alt')} "
|
||||||
|
|
||||||
|
Handle private channel menu
|
||||||
|
|
||||||
|
$('#privateChannelsMenu').on 'click', '.privateChannel', ->
|
||||||
|
openPrivateChannel $(@).data 'privateChannelID'
|
||||||
|
|
||||||
Handle submitting the form. The message will be validated by some basic checks, passed to the `submit` eventlisteners
|
Handle submitting the form. The message will be validated by some basic checks, passed to the `submit` eventlisteners
|
||||||
and afterwards sent to the server by an AJAX request.
|
and afterwards sent to the server by an AJAX request.
|
||||||
|
|
||||||
$('#timsChatForm').submit (event) ->
|
$('#timsChatForm').submit (event) ->
|
||||||
event.preventDefault()
|
do event.preventDefault
|
||||||
|
|
||||||
text = $('#timsChatInput').val().trim()
|
text = do $('#timsChatInput').val().trim
|
||||||
$('#timsChatInput').val('').focus().keyup()
|
$('#timsChatInput').val('').focus().keyup()
|
||||||
|
|
||||||
return false if text.length is 0
|
return false if text.length is 0
|
||||||
|
|
||||||
|
unless openChannel is 0
|
||||||
|
text = "/whisper #{userList.allTime[openChannel].username}, #{text}"
|
||||||
|
|
||||||
# Free the fish!
|
# Free the fish!
|
||||||
freeTheFish() if text.toLowerCase() is '/free the fish'
|
do freeTheFish if text.toLowerCase() is '/free the fish'
|
||||||
|
|
||||||
text = do (text) ->
|
text = do (text) ->
|
||||||
obj =
|
obj =
|
||||||
@ -139,16 +156,13 @@ and afterwards sent to the server by an AJAX request.
|
|||||||
enableSmilies: $('#timsChatSmilies').data 'status'
|
enableSmilies: $('#timsChatSmilies').data 'status'
|
||||||
showLoadingOverlay: false
|
showLoadingOverlay: false
|
||||||
success: ->
|
success: ->
|
||||||
$('#timsChatInputContainer').removeClass('formError').find('.innerError').hide()
|
do hideInputError
|
||||||
getMessages()
|
|
||||||
|
do getMessages
|
||||||
failure: (data) ->
|
failure: (data) ->
|
||||||
return true unless (data?.returnValues?.errorType?) or (data?.message?)
|
return true unless (data?.returnValues?.errorType?) or (data?.message?)
|
||||||
|
|
||||||
$('#timsChatInputContainer').addClass('formError').find('.innerError').show().html (data?.returnValues?.errorType) ? data.message
|
showInputError (data?.returnValues?.errorType) ? data.message
|
||||||
|
|
||||||
setTimeout ->
|
|
||||||
$('#timsChatInputContainer').removeClass('formError').find('.innerError').hide()
|
|
||||||
, 5e3
|
|
||||||
|
|
||||||
false
|
false
|
||||||
|
|
||||||
@ -157,11 +171,11 @@ The the word the caret is in will be passed to `autocomplete` and replaced if a
|
|||||||
|
|
||||||
$('#timsChatInput').keydown (event) ->
|
$('#timsChatInput').keydown (event) ->
|
||||||
if event.keyCode is $.ui.keyCode.TAB
|
if event.keyCode is $.ui.keyCode.TAB
|
||||||
input = $(event.currentTarget)
|
do event.preventDefault
|
||||||
event.preventDefault()
|
input = $ @
|
||||||
|
|
||||||
autocomplete.value ?= input.val()
|
autocomplete.value ?= do input.val
|
||||||
autocomplete.caret ?= input.getCaret()
|
autocomplete.caret ?= do input.getCaret
|
||||||
|
|
||||||
beforeCaret = autocomplete.value.substring 0, autocomplete.caret
|
beforeCaret = autocomplete.value.substring 0, autocomplete.caret
|
||||||
lastSpace = beforeCaret.lastIndexOf ' '
|
lastSpace = beforeCaret.lastIndexOf ' '
|
||||||
@ -177,7 +191,7 @@ The the word the caret is in will be passed to `autocomplete` and replaced if a
|
|||||||
return if toComplete.length is 0
|
return if toComplete.length is 0
|
||||||
console.log "Autocompleting '#{toComplete}'"
|
console.log "Autocompleting '#{toComplete}'"
|
||||||
|
|
||||||
if beforeComplete is '' and toComplete.substring(0, 1) is '/'
|
if beforeComplete is '' and (toComplete.substring 0, 1) is '/'
|
||||||
regex = new RegExp "^#{WCF.String.escapeRegExp toComplete.substring 1}", "i"
|
regex = new RegExp "^#{WCF.String.escapeRegExp toComplete.substring 1}", "i"
|
||||||
# TODO: Proper command list
|
# TODO: Proper command list
|
||||||
commands = (command for command in v.config.installedCommands when regex.test command)
|
commands = (command for command in v.config.installedCommands when regex.test command)
|
||||||
@ -185,7 +199,10 @@ The the word the caret is in will be passed to `autocomplete` and replaced if a
|
|||||||
toComplete = '/' + commands[autocomplete.offset++ % commands.length] + ' ' if commands.length isnt 0
|
toComplete = '/' + commands[autocomplete.offset++ % commands.length] + ' ' if commands.length isnt 0
|
||||||
else
|
else
|
||||||
regex = new RegExp "^#{WCF.String.escapeRegExp toComplete}", "i"
|
regex = new RegExp "^#{WCF.String.escapeRegExp toComplete}", "i"
|
||||||
users = (username for user in $('.timsChatUser') when regex.test(username = $(user).data('username')))
|
|
||||||
|
users = [ ]
|
||||||
|
for userID, user of userList.current
|
||||||
|
users.push user.username if regex.test user.username
|
||||||
|
|
||||||
toComplete = users[autocomplete.offset++ % users.length] + ', ' if users.length isnt 0
|
toComplete = users[autocomplete.offset++ % users.length] + ', ' if users.length isnt 0
|
||||||
|
|
||||||
@ -195,7 +212,7 @@ The the word the caret is in will be passed to `autocomplete` and replaced if a
|
|||||||
Reset autocompleter to default status, when a key is pressed that is not TAB.
|
Reset autocompleter to default status, when a key is pressed that is not TAB.
|
||||||
|
|
||||||
else
|
else
|
||||||
$('#timsChatInput').click()
|
do $('#timsChatInput').click
|
||||||
|
|
||||||
Reset autocompleter to default status, when the input is `click`ed, as the position of the caret may have changed.
|
Reset autocompleter to default status, when the input is `click`ed, as the position of the caret may have changed.
|
||||||
|
|
||||||
@ -208,14 +225,14 @@ Reset autocompleter to default status, when the input is `click`ed, as the posit
|
|||||||
Refresh the room list when the associated button is `click`ed.
|
Refresh the room list when the associated button is `click`ed.
|
||||||
|
|
||||||
$('#timsChatRoomList button').click ->
|
$('#timsChatRoomList button').click ->
|
||||||
refreshRoomList()
|
do refreshRoomList
|
||||||
|
|
||||||
Clear the chat by removing every single message once the clear button is `clicked`.
|
Clear the chat by removing every single message once the clear button is `clicked`.
|
||||||
|
|
||||||
$('#timsChatClear').click (event) ->
|
$('#timsChatClear').click (event) ->
|
||||||
event.preventDefault()
|
do event.preventDefault
|
||||||
$('.timsChatMessage').remove()
|
do $('.timsChatMessageContainer.active .timsChatMessage').remove
|
||||||
$('#timsChatMessageContainer').scrollTop $('#timsChatMessageContainer').prop('scrollHeight')
|
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop 'scrollHeight'
|
||||||
|
|
||||||
Handle toggling of the toggleable buttons.
|
Handle toggling of the toggleable buttons.
|
||||||
|
|
||||||
@ -230,7 +247,7 @@ Handle toggling of the toggleable buttons.
|
|||||||
element.addClass 'active'
|
element.addClass 'active'
|
||||||
element.attr 'title', element.data 'disableMessage'
|
element.attr 'title', element.data 'disableMessage'
|
||||||
|
|
||||||
$('#timsChatInput').focus()
|
do $('#timsChatInput').focus
|
||||||
|
|
||||||
Mark smilies as disabled when they are disabled.
|
Mark smilies as disabled when they are disabled.
|
||||||
|
|
||||||
@ -251,7 +268,7 @@ Toggle fullscreen mode.
|
|||||||
else
|
else
|
||||||
$('html').removeClass 'fullscreen'
|
$('html').removeClass 'fullscreen'
|
||||||
|
|
||||||
Toggle checkboxes
|
Toggle checkboxes.
|
||||||
|
|
||||||
$('#timsChatMark').click (event) ->
|
$('#timsChatMark').click (event) ->
|
||||||
if $(@).data 'status'
|
if $(@).data 'status'
|
||||||
@ -259,6 +276,14 @@ Toggle checkboxes
|
|||||||
else
|
else
|
||||||
$('.timsChatMessageContainer').removeClass 'markEnabled'
|
$('.timsChatMessageContainer').removeClass 'markEnabled'
|
||||||
|
|
||||||
|
Hide topic container.
|
||||||
|
|
||||||
|
$('.jsTopicCloser').on 'click', ->
|
||||||
|
if $('.timsChatMessageContainer.active').data('userID') is 0
|
||||||
|
$('#timsChatTopic').addClass 'hidden'
|
||||||
|
else
|
||||||
|
closePrivateChannel $('.timsChatMessageContainer.active').data('userID')
|
||||||
|
|
||||||
Visibly mark the message once the associated checkbox is checked.
|
Visibly mark the message once the associated checkbox is checked.
|
||||||
|
|
||||||
$(document).on 'click', '.timsChatMessage :checkbox', (event) ->
|
$(document).on 'click', '.timsChatMessage :checkbox', (event) ->
|
||||||
@ -271,9 +296,9 @@ Scroll down when autoscroll is being activated.
|
|||||||
|
|
||||||
$('#timsChatAutoscroll').click (event) ->
|
$('#timsChatAutoscroll').click (event) ->
|
||||||
if $('#timsChatAutoscroll').data 'status'
|
if $('#timsChatAutoscroll').data 'status'
|
||||||
$('#timsChatMessageContainer').scrollTop $('#timsChatMessageContainer').prop('scrollHeight')
|
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop 'scrollHeight'
|
||||||
|
|
||||||
$('#timsChatMessageContainer').on 'scroll', (event) ->
|
$('.timsChatMessageContainer.active').on 'scroll', (event) ->
|
||||||
element = $ @
|
element = $ @
|
||||||
scrollTop = element.scrollTop()
|
scrollTop = element.scrollTop()
|
||||||
scrollHeight = element.prop 'scrollHeight'
|
scrollHeight = element.prop 'scrollHeight'
|
||||||
@ -282,13 +307,13 @@ Scroll down when autoscroll is being activated.
|
|||||||
if scrollTop < scrollHeight - height - 25
|
if scrollTop < scrollHeight - height - 25
|
||||||
if $('#timsChatAutoscroll').data('status') is 1
|
if $('#timsChatAutoscroll').data('status') is 1
|
||||||
scrollUpNotifications = on
|
scrollUpNotifications = on
|
||||||
$('#timsChatAutoscroll').click()
|
do $('#timsChatAutoscroll').click
|
||||||
|
|
||||||
if scrollTop > scrollHeight - height - 10
|
if scrollTop > scrollHeight - height - 10
|
||||||
if $('#timsChatAutoscroll').data('status') is 0
|
if $('#timsChatAutoscroll').data('status') is 0
|
||||||
scrollUpNotifications = off
|
scrollUpNotifications = off
|
||||||
$(@).removeClass 'notification'
|
$(@).removeClass 'notification'
|
||||||
$('#timsChatAutoscroll').click()
|
do $('#timsChatAutoscroll').click
|
||||||
|
|
||||||
Enable duplicate tab detection.
|
Enable duplicate tab detection.
|
||||||
|
|
||||||
@ -321,11 +346,11 @@ load messages if the appropriate event arrives.
|
|||||||
do ->
|
do ->
|
||||||
be.bastelstu.wcf.nodePush.onConnect ->
|
be.bastelstu.wcf.nodePush.onConnect ->
|
||||||
console.log 'Disabling periodic loading'
|
console.log 'Disabling periodic loading'
|
||||||
pe.getMessages.stop()
|
do pe.getMessages.stop
|
||||||
|
|
||||||
be.bastelstu.wcf.nodePush.onDisconnect ->
|
be.bastelstu.wcf.nodePush.onDisconnect ->
|
||||||
console.log 'Enabling periodic loading'
|
console.log 'Enabling periodic loading'
|
||||||
getMessages()
|
do getMessages
|
||||||
pe.getMessages = new WCF.PeriodicalExecuter getMessages, v.config.reloadTime * 1e3
|
pe.getMessages = new WCF.PeriodicalExecuter getMessages, v.config.reloadTime * 1e3
|
||||||
|
|
||||||
be.bastelstu.wcf.nodePush.onMessage 'be.bastelstu.chat.newMessage', getMessages
|
be.bastelstu.wcf.nodePush.onMessage 'be.bastelstu.chat.newMessage', getMessages
|
||||||
@ -334,18 +359,37 @@ load messages if the appropriate event arrives.
|
|||||||
Finished! Enable the input now and join the chat.
|
Finished! Enable the input now and join the chat.
|
||||||
|
|
||||||
join roomID
|
join roomID
|
||||||
$('#timsChatInput').enable().jCounter().focus();
|
do $('#timsChatInput').enable().jCounter().focus
|
||||||
|
|
||||||
console.log "Finished initializing"
|
console.log "Finished initializing"
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
||||||
|
Shows an error message below the input.
|
||||||
|
|
||||||
|
showInputError = (message) ->
|
||||||
|
$('#timsChatInputContainer').addClass('formError').find('.innerError').show().html message
|
||||||
|
|
||||||
|
clearTimeout inputErrorHidingTimer if inputErrorHidingTimer?
|
||||||
|
inputErrorHidingTimer = setTimeout ->
|
||||||
|
do hideInputError
|
||||||
|
, 5e3
|
||||||
|
|
||||||
|
Hides the error message below the input.
|
||||||
|
|
||||||
|
hideInputError = ->
|
||||||
|
clearTimeout inputErrorHidingTimer if inputErrorHidingTimer?
|
||||||
|
inputErrorHidingTimer = null
|
||||||
|
|
||||||
|
do $('#timsChatInputContainer').removeClass('formError').find('.innerError').hide
|
||||||
|
|
||||||
Free the fish.
|
Free the fish.
|
||||||
|
|
||||||
freeTheFish = ->
|
freeTheFish = ->
|
||||||
return if $.wcfIsset 'fish'
|
return if $.wcfIsset 'fish'
|
||||||
console.warn 'Freeing the fish'
|
console.warn 'Freeing the fish'
|
||||||
fish = $ """<div id="fish">#{WCF.String.escapeHTML('><((((\u00B0>')}</div>"""
|
fish = $ """<div id="fish">#{WCF.String.escapeHTML('><((((\u00B0>')}</div>"""
|
||||||
|
|
||||||
fish.css
|
fish.css
|
||||||
position: 'absolute'
|
position: 'absolute'
|
||||||
top: '150px'
|
top: '150px'
|
||||||
@ -389,7 +433,7 @@ Fetch new messages from the server and pass them to `handleMessages`. The userli
|
|||||||
error: ->
|
error: ->
|
||||||
console.error "Message loading failed, #{--remainingFailures} remaining"
|
console.error "Message loading failed, #{--remainingFailures} remaining"
|
||||||
if remainingFailures <= 0
|
if remainingFailures <= 0
|
||||||
freeTheFish()
|
do freeTheFish
|
||||||
console.error 'To many failures, aborting'
|
console.error 'To many failures, aborting'
|
||||||
|
|
||||||
showError WCF.Language.get 'chat.error.onMessageLoad'
|
showError WCF.Language.get 'chat.error.onMessageLoad'
|
||||||
@ -406,12 +450,24 @@ Prevent loading messages in parallel.
|
|||||||
Insert the given messages into the chat stream.
|
Insert the given messages into the chat stream.
|
||||||
|
|
||||||
handleMessages = (messages) ->
|
handleMessages = (messages) ->
|
||||||
$('#timsChatMessageContainer').trigger 'scroll'
|
$('.timsChatMessageContainer.active').trigger 'scroll'
|
||||||
|
|
||||||
for message in messages
|
for message in messages
|
||||||
|
message.isInPrivateChannel = (String(message.type) is v.config.messageTypes.WHISPER) and ($.wcfIsset("timsChatMessageContainer#{message.receiver}") or $.wcfIsset("timsChatMessageContainer#{message.sender}"))
|
||||||
|
|
||||||
events.newMessage.fire message
|
events.newMessage.fire message
|
||||||
|
|
||||||
output = v.messageTemplate.fetch message
|
createNewMessage = yes
|
||||||
|
if $('.timsChatMessage:last-child .text').is('ul') and lastMessage isnt null and lastMessage.type in [ 0, 7 ]
|
||||||
|
if lastMessage.type is message.type and lastMessage.sender is message.sender and lastMessage.receiver is message.receiver and lastMessage.isInPrivateChannel is message.isInPrivateChannel
|
||||||
|
createNewMessage = no
|
||||||
|
|
||||||
|
if createNewMessage
|
||||||
|
message.isFollowUp = no
|
||||||
|
output = v.messageTemplate.fetch
|
||||||
|
message: message
|
||||||
|
messageTypes: v.config.messageTypes
|
||||||
|
|
||||||
li = $ '<li></li>'
|
li = $ '<li></li>'
|
||||||
li.addClass 'timsChatMessage'
|
li.addClass 'timsChatMessage'
|
||||||
li.addClass "timsChatMessage#{message.type}"
|
li.addClass "timsChatMessage#{message.type}"
|
||||||
@ -419,16 +475,40 @@ Insert the given messages into the chat stream.
|
|||||||
li.addClass 'ownMessage' if message.sender is WCF.User.userID
|
li.addClass 'ownMessage' if message.sender is WCF.User.userID
|
||||||
li.append output
|
li.append output
|
||||||
|
|
||||||
li.appendTo $ '#timsChatMessageContainer > ul'
|
if message.isInPrivateChannel and message.sender is WCF.User.userID
|
||||||
|
li.appendTo $ "#timsChatMessageContainer#{message.receiver} > ul"
|
||||||
|
else if message.isInPrivateChannel
|
||||||
|
li.appendTo $ "#timsChatMessageContainer#{message.sender} > ul"
|
||||||
|
else
|
||||||
|
li.appendTo $ '#timsChatMessageContainer0 > ul'
|
||||||
|
else
|
||||||
|
message.isFollowUp = yes
|
||||||
|
output = v.messageTemplate.fetch
|
||||||
|
message: message
|
||||||
|
messageTypes: v.config.messageTypes
|
||||||
|
|
||||||
$('#timsChatMessageContainer').scrollTop $('#timsChatMessageContainer').prop('scrollHeight') if $('#timsChatAutoscroll').data('status') is 1
|
if message.isInPrivateChannel and message.sender is WCF.User.userID
|
||||||
|
messageContainerID = message.receiver
|
||||||
|
else if message.isInPrivateChannel
|
||||||
|
messageContainerID = message.sender
|
||||||
|
else
|
||||||
|
messageContainerID = 0
|
||||||
|
|
||||||
|
$("#timsChatMessageContainer#{messageContainerID} .timsChatMessage:last-child .text").append $(output).find('.text li:last-child')
|
||||||
|
|
||||||
|
lastMessage = message
|
||||||
|
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop('scrollHeight') if $('#timsChatAutoscroll').data('status') is 1
|
||||||
|
|
||||||
Rebuild the userlist based on the given `users`.
|
Rebuild the userlist based on the given `users`.
|
||||||
|
|
||||||
handleUsers = (users) ->
|
handleUsers = (users) ->
|
||||||
foundUsers = { }
|
foundUsers = { }
|
||||||
|
userList.current = { }
|
||||||
|
|
||||||
for user in users
|
for user in users
|
||||||
|
do (user) ->
|
||||||
|
userList.current[user.userID] = userList.allTime[user.userID] = user
|
||||||
|
|
||||||
id = "timsChatUser#{user.userID}"
|
id = "timsChatUser#{user.userID}"
|
||||||
|
|
||||||
Move the user to the new position if he was found in the old list.
|
Move the user to the new position if he was found in the old list.
|
||||||
@ -471,15 +551,18 @@ Build HTML of the user and insert it into the list, if the users was not found i
|
|||||||
li.append v.userTemplate.fetch user
|
li.append v.userTemplate.fetch user
|
||||||
|
|
||||||
menu = $ '<ul></ul>'
|
menu = $ '<ul></ul>'
|
||||||
menu.addClass 'dropdownMenu'
|
unless user.userID is WCF.User.userID
|
||||||
menu.append $ "<li><a>#{WCF.Language.get('chat.general.query')}</a></li>"
|
menu.append $("<li><a>#{WCF.Language.get('chat.general.query')}</a></li>").click -> openPrivateChannel user.userID
|
||||||
menu.append $ "<li><a>#{WCF.Language.get('chat.general.kick')}</a></li>"
|
menu.append $ "<li><a>#{WCF.Language.get('chat.general.kick')}</a></li>"
|
||||||
menu.append $ "<li><a>#{WCF.Language.get('chat.general.ban')}</a></li>"
|
menu.append $ "<li><a>#{WCF.Language.get('chat.general.ban')}</a></li>"
|
||||||
menu.append $ """<li><a href="#{user.link}">#{WCF.Language.get('chat.general.profile')}</a></li>"""
|
menu.append $ """<li><a href="#{user.link}">#{WCF.Language.get('chat.general.profile')}</a></li>"""
|
||||||
|
|
||||||
events.userMenu.fire user, menu
|
events.userMenu.fire user, menu
|
||||||
|
|
||||||
|
if menu.find('li').length
|
||||||
li.append menu
|
li.append menu
|
||||||
|
menu.addClass 'dropdownMenu'
|
||||||
|
|
||||||
li.appendTo $ '#timsChatUserList > ul'
|
li.appendTo $ '#timsChatUserList > ul'
|
||||||
|
|
||||||
foundUsers[id] = true
|
foundUsers[id] = true
|
||||||
@ -489,7 +572,7 @@ Remove all users that left the chat.
|
|||||||
$('.timsChatUser').each ->
|
$('.timsChatUser').each ->
|
||||||
unless foundUsers[$(@).attr('id')]?
|
unless foundUsers[$(@).attr('id')]?
|
||||||
console.log "Removing User: '#{$(@).data('username')}'"
|
console.log "Removing User: '#{$(@).data('username')}'"
|
||||||
$(@).remove();
|
do $(@).remove
|
||||||
|
|
||||||
|
|
||||||
$('#toggleUsers .badge').text $('.timsChatUser').length
|
$('#toggleUsers .badge').text $('.timsChatUser').length
|
||||||
@ -505,18 +588,29 @@ the existing text. If `options.submit` is true the message will be sent to the s
|
|||||||
|
|
||||||
text = $('#timsChatInput').val() + text if options.append
|
text = $('#timsChatInput').val() + text if options.append
|
||||||
$('#timsChatInput').val text
|
$('#timsChatInput').val text
|
||||||
$('#timsChatInput').keyup()
|
do $('#timsChatInput').keyup
|
||||||
|
|
||||||
if (options.submit)
|
if options.submit
|
||||||
$('#timsChatForm').submit()
|
do $('#timsChatForm').submit
|
||||||
else
|
else
|
||||||
$('#timsChatInput').focus()
|
do $('#timsChatInput').focus
|
||||||
|
|
||||||
Send out notifications for the given `message`. The number of unread messages will be prepended to `document.title` and if available desktop notifications will be sent.
|
Send out notifications for the given `message`. The number of unread messages will be prepended to `document.title` and if available desktop notifications will be sent.
|
||||||
|
|
||||||
notify = (message) ->
|
notify = (message) ->
|
||||||
if scrollUpNotifications
|
if scrollUpNotifications
|
||||||
$('#timsChatMessageContainer').addClass 'notification'
|
$('.timsChatMessageContainer.active').addClass 'notification'
|
||||||
|
|
||||||
|
if message.isInPrivateChannel
|
||||||
|
if message.sender is WCF.User.userID
|
||||||
|
privateChannelID = message.receiver
|
||||||
|
else
|
||||||
|
privateChannelID = message.sender
|
||||||
|
|
||||||
|
if $('.timsChatMessageContainer.active').data('userID') isnt privateChannelID
|
||||||
|
$("#privateChannel#{privateChannelID}").addClass 'notify'
|
||||||
|
else if $('.timsChatMessageContainer.active').data('userID') isnt 0
|
||||||
|
$("#privateChannel0").addClass 'notify'
|
||||||
|
|
||||||
return if isActive or $('#timsChatNotify').data('status') is 0
|
return if isActive or $('#timsChatNotify').data('status') is 0
|
||||||
|
|
||||||
@ -532,9 +626,9 @@ Send out notifications for the given `message`. The number of unread messages wi
|
|||||||
notification = new window.Notification title,
|
notification = new window.Notification title,
|
||||||
body: content
|
body: content
|
||||||
onclick: ->
|
onclick: ->
|
||||||
notification.close()
|
do notification.close
|
||||||
setTimeout ->
|
setTimeout ->
|
||||||
notification.close()
|
do notification.close
|
||||||
, 5e3
|
, 5e3
|
||||||
|
|
||||||
Fetch the roomlist from the server and update it in the GUI.
|
Fetch the roomlist from the server and update it in the GUI.
|
||||||
@ -550,7 +644,7 @@ Fetch the roomlist from the server and update it in the GUI.
|
|||||||
showLoadingOverlay: false
|
showLoadingOverlay: false
|
||||||
suppressErrors: true
|
suppressErrors: true
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
$('.timsChatRoom').remove()
|
do $('.timsChatRoom').remove
|
||||||
$('#toggleRooms .badge').text data.returnValues.length
|
$('#toggleRooms .badge').text data.returnValues.length
|
||||||
|
|
||||||
for room in data.returnValues
|
for room in data.returnValues
|
||||||
@ -561,8 +655,8 @@ Fetch the roomlist from the server and update it in the GUI.
|
|||||||
|
|
||||||
if window.history?.replaceState?
|
if window.history?.replaceState?
|
||||||
$('.timsChatRoom').click (event) ->
|
$('.timsChatRoom').click (event) ->
|
||||||
event.preventDefault()
|
do event.preventDefault
|
||||||
target = $(@)
|
target = $ @
|
||||||
|
|
||||||
window.history.replaceState {}, '', target.attr 'href'
|
window.history.replaceState {}, '', target.attr 'href'
|
||||||
|
|
||||||
@ -580,8 +674,8 @@ Shows an unrecoverable error with the given text.
|
|||||||
|
|
||||||
loading = true
|
loading = true
|
||||||
|
|
||||||
pe.refreshRoomList.stop()
|
do pe.refreshRoomList.stop
|
||||||
pe.getMessages.stop()
|
do pe.getMessages.stop
|
||||||
|
|
||||||
errorDialog = $("""
|
errorDialog = $("""
|
||||||
<div id="timsChatLoadingErrorDialog">
|
<div id="timsChatLoadingErrorDialog">
|
||||||
@ -592,7 +686,7 @@ Shows an unrecoverable error with the given text.
|
|||||||
formSubmit = $("""<div class="formSubmit"></div>""").appendTo errorDialog
|
formSubmit = $("""<div class="formSubmit"></div>""").appendTo errorDialog
|
||||||
reloadButton = $("""<button class="buttonPrimary">#{WCF.Language.get 'chat.error.reload'}</button>""").appendTo formSubmit
|
reloadButton = $("""<button class="buttonPrimary">#{WCF.Language.get 'chat.error.reload'}</button>""").appendTo formSubmit
|
||||||
reloadButton.on 'click', ->
|
reloadButton.on 'click', ->
|
||||||
window.location.reload()
|
do window.location.reload
|
||||||
|
|
||||||
$('#timsChatLoadingErrorDialog').wcfDialog
|
$('#timsChatLoadingErrorDialog').wcfDialog
|
||||||
closable: false
|
closable: false
|
||||||
@ -612,35 +706,116 @@ Joins a room.
|
|||||||
success: (data) ->
|
success: (data) ->
|
||||||
loading = false
|
loading = false
|
||||||
|
|
||||||
$('#timsChatTopic').text data.returnValues.topic
|
$('#timsChatTopic').removeClass 'hidden'
|
||||||
if data.returnValues.topic.trim() is ''
|
currentRoom = data.returnValues
|
||||||
|
currentRoom.roomID = roomID
|
||||||
|
|
||||||
|
$('#timsChatTopic > .topic').text currentRoom.topic
|
||||||
|
if currentRoom.topic.trim() is ''
|
||||||
$('#timsChatTopic').addClass 'empty'
|
$('#timsChatTopic').addClass 'empty'
|
||||||
else
|
else
|
||||||
$('#timsChatTopic').removeClass 'empty'
|
$('#timsChatTopic').removeClass 'empty'
|
||||||
|
|
||||||
$('.timsChatMessage').addClass 'unloaded'
|
$('.timsChatMessage').addClass 'unloaded'
|
||||||
|
|
||||||
document.title = v.titleTemplate.fetch data.returnValues
|
document.title = v.titleTemplate.fetch currentRoom
|
||||||
handleMessages data.returnValues.messages
|
handleMessages currentRoom.messages
|
||||||
getMessages()
|
do getMessages
|
||||||
refreshRoomList()
|
do refreshRoomList
|
||||||
failure: ->
|
failure: ->
|
||||||
showError WCF.Language.get 'chat.error.join'
|
showError WCF.Language.get 'chat.error.join'
|
||||||
|
|
||||||
|
Open private channel
|
||||||
|
|
||||||
|
openPrivateChannel = (userID) ->
|
||||||
|
userID = parseInt userID
|
||||||
|
|
||||||
|
console.log "Opening private channel #{userID}"
|
||||||
|
|
||||||
|
unless $.wcfIsset "timsChatMessageContainer#{userID}"
|
||||||
|
return unless userList.allTime[userID]?
|
||||||
|
|
||||||
|
div = $ '<div>'
|
||||||
|
div.attr 'id', "timsChatMessageContainer#{userID}"
|
||||||
|
div.data 'userID', userID
|
||||||
|
div.addClass 'timsChatMessageContainer'
|
||||||
|
div.addClass 'marginTop'
|
||||||
|
div.addClass 'container'
|
||||||
|
div.wrapInner '<ul>'
|
||||||
|
$('#timsChatMessageContainer0').after div
|
||||||
|
|
||||||
|
$('.privateChannel').removeClass 'active'
|
||||||
|
if userID isnt 0
|
||||||
|
$('#timsChatTopic').removeClass 'hidden empty'
|
||||||
|
$('#timsChatTopic > .topic').text WCF.Language.get 'chat.general.privateChannelTopic', {username: userList.allTime[userID].username}
|
||||||
|
$('#timsChatTopic > .jsTopicCloser').attr 'title', WCF.Language.get 'chat.general.closePrivateChannel'
|
||||||
|
|
||||||
|
unless $.wcfIsset "privateChannel#{userID}"
|
||||||
|
li = $ '<li>'
|
||||||
|
li.attr 'id', "privateChannel#{userID}"
|
||||||
|
li.data 'privateChannelID', userID
|
||||||
|
li.addClass 'privateChannel'
|
||||||
|
|
||||||
|
span = $ '<span class="userAvatar framed" />'
|
||||||
|
|
||||||
|
avatar = $ userList.allTime[userID].avatar[16]
|
||||||
|
avatar.addClass 'jsTooltip'
|
||||||
|
avatar.attr 'title', userList.allTime[userID].username
|
||||||
|
avatar.wrap span
|
||||||
|
li.append avatar.parent().addClass 'small'
|
||||||
|
|
||||||
|
avatar = $ userList.allTime[userID].avatar[32]
|
||||||
|
avatar.addClass 'jsTooltip'
|
||||||
|
avatar.attr 'title', userList.allTime[userID].username
|
||||||
|
avatar.wrap span
|
||||||
|
li.append avatar.parent().addClass 'large'
|
||||||
|
|
||||||
|
$('#privateChannelsMenu ul').append li
|
||||||
|
|
||||||
|
$('#privateChannelsMenu').addClass 'shown'
|
||||||
|
else
|
||||||
|
$('#timsChatTopic > .topic').text currentRoom.topic
|
||||||
|
$('#timsChatTopic > .jsTopicCloser').attr 'title', WCF.Language.get 'chat.general.closeTopic'
|
||||||
|
if currentRoom.topic.trim() is ''
|
||||||
|
$('#timsChatTopic').addClass 'empty'
|
||||||
|
else
|
||||||
|
$('#timsChatTopic').removeClass 'empty'
|
||||||
|
|
||||||
|
do WCF.DOMNodeInsertedHandler.execute
|
||||||
|
|
||||||
|
$('.timsChatMessageContainer').removeClass 'active'
|
||||||
|
$("#timsChatMessageContainer#{userID}").addClass 'active'
|
||||||
|
$("#privateChannel#{userID}").addClass('active').removeClass 'notify'
|
||||||
|
openChannel = userID
|
||||||
|
|
||||||
|
Close private channel
|
||||||
|
|
||||||
|
closePrivateChannel = (userID) ->
|
||||||
|
unless userID is 0
|
||||||
|
do $("#privateChannel#{userID}").remove
|
||||||
|
do $("#timsChatMessageContainer#{userID}").remove
|
||||||
|
|
||||||
|
if $('#privateChannelsMenu li').length <= 1
|
||||||
|
$('#privateChannelsMenu').removeClass 'shown'
|
||||||
|
|
||||||
|
openPrivateChannel 0
|
||||||
|
|
||||||
Bind the given callback to the given event.
|
Bind the given callback to the given event.
|
||||||
|
|
||||||
addListener = (event, callback) ->
|
addListener = (event, callback) ->
|
||||||
return false unless events[event]?
|
return false unless events[event]?
|
||||||
|
|
||||||
events[event].add callback
|
events[event].add callback
|
||||||
|
|
||||||
|
true
|
||||||
|
|
||||||
Remove the given callback from the given event.
|
Remove the given callback from the given event.
|
||||||
|
|
||||||
removeListener = (event, callback) ->
|
removeListener = (event, callback) ->
|
||||||
return false unless events[event]?
|
return false unless events[event]?
|
||||||
|
|
||||||
events[event].remove callback
|
events[event].remove callback
|
||||||
|
|
||||||
|
true
|
||||||
|
|
||||||
And finally export the public methods and variables.
|
And finally export the public methods and variables.
|
||||||
|
|
||||||
Chat =
|
Chat =
|
||||||
@ -650,6 +825,8 @@ And finally export the public methods and variables.
|
|||||||
insertText: insertText
|
insertText: insertText
|
||||||
freeTheFish: freeTheFish
|
freeTheFish: freeTheFish
|
||||||
join: join
|
join: join
|
||||||
|
closePrivateChannel: closePrivateChannel # TODO: REMOVE AFTER DEBUGGING
|
||||||
|
openPrivateChannel: openPrivateChannel # TODO: REMOVE AFTER DEBUGGING
|
||||||
listener:
|
listener:
|
||||||
add: addListener
|
add: addListener
|
||||||
remove: removeListener
|
remove: removeListener
|
||||||
|
@ -116,7 +116,7 @@ public function save() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
\wcf\system\acl\ACLHandler::getInstance()->save($roomID, $this->objectTypeID);
|
\wcf\system\acl\ACLHandler::getInstance()->save($roomID, $this->objectTypeID);
|
||||||
\chat\system\permission\permissionHandler::clearCache();
|
\chat\system\permission\PermissionHandler::clearCache();
|
||||||
|
|
||||||
$this->saved();
|
$this->saved();
|
||||||
|
|
||||||
|
172
file/lib/acp/page/ChatSuspensionListPage.class.php
Normal file
172
file/lib/acp/page/ChatSuspensionListPage.class.php
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\acp\page;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists chat suspensions.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage acp.page
|
||||||
|
*/
|
||||||
|
class ChatSuspensionListPage extends \wcf\page\SortablePage {
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$activeMenuItem
|
||||||
|
*/
|
||||||
|
public $activeMenuItem = 'chat.acp.menu.link.suspension.list';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\AbstractPage::$neededPermissions
|
||||||
|
*/
|
||||||
|
public $neededPermissions = array('admin.chat.canManageSuspensions');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\SortablePage::$defaultSortField
|
||||||
|
*/
|
||||||
|
public $defaultSortField = 'expires';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\SortablePage::$validSortFields
|
||||||
|
*/
|
||||||
|
public $validSortFields = array('suspensionID', 'userID', 'username', 'roomID', 'type', 'expires', 'issuer', 'time', 'reason');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\MultipleLinkPage::$objectListClassName
|
||||||
|
*/
|
||||||
|
public $objectListClassName = 'chat\data\suspension\SuspensionList';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* type filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterSuspensionType = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterUserID = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* username
|
||||||
|
*
|
||||||
|
* @var String
|
||||||
|
*/
|
||||||
|
public $filterUsername = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* issuer filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterIssuerUserID = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* issuer username
|
||||||
|
*
|
||||||
|
* @var String
|
||||||
|
*/
|
||||||
|
public $filterIssuerUsername = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* room filter
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $filterRoomID = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* display revoked suspensions
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $displayRevoked = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\IPage::readParameters()
|
||||||
|
*/
|
||||||
|
public function readParameters() {
|
||||||
|
parent::readParameters();
|
||||||
|
|
||||||
|
// get usernames
|
||||||
|
if (isset($_REQUEST['username']) && !empty($_REQUEST['username'])) $this->filterUsername = \wcf\util\StringUtil::trim($_REQUEST['username']);
|
||||||
|
if (isset($_REQUEST['issuerUsername']) && !empty($_REQUEST['issuerUsername'])) $this->filterIssuerUsername = \wcf\util\StringUtil::trim($_REQUEST['issuerUsername']);
|
||||||
|
|
||||||
|
// get user IDs by username
|
||||||
|
if ($this->filterUsername != null) $this->filterUserID = \wcf\data\user\UserProfile::getUserProfileByUsername($this->filterUsername)->userID;
|
||||||
|
if ($this->filterIssuerUsername != null) $this->filterIssuerUserID = \wcf\data\user\UserProfile::getUserProfileByUsername($this->filterIssuerUsername)->userID;
|
||||||
|
|
||||||
|
// get user IDs by request if no username was sent
|
||||||
|
if ($this->filterUserID === null && isset($_REQUEST['userID']) && !empty($_REQUEST['userID'])) $this->filterUserID = intval($_REQUEST['userID']);
|
||||||
|
if ($this->filterIssuerUserID === null && isset($_REQUEST['issuerUserID']) && !empty($_REQUEST['issuerUserID'])) $this->filterIssuerUserID = intval($_REQUEST['issuerUserID']);
|
||||||
|
|
||||||
|
// get usernames by ID if no usernames were sent
|
||||||
|
if ($this->filterUsername === null) $this->filterUsername = \wcf\data\user\UserProfile::getUserProfile($this->filterUserID);
|
||||||
|
if ($this->filterIssuerUsername === null) $this->filterIssuerUsername = \wcf\data\user\UserProfile::getUserProfile($this->filterIssuerUserID);
|
||||||
|
|
||||||
|
// get room IDs by request
|
||||||
|
if (isset($_REQUEST['roomID']) && $_REQUEST['roomID'] != -1) $this->filterRoomID = intval($_REQUEST['roomID']);
|
||||||
|
if (isset($_REQUEST['suspensionType']) && !empty($_REQUEST['suspensionType'])) $this->filterSuspensionType = intval($_REQUEST['suspensionType']);
|
||||||
|
|
||||||
|
// display revoked
|
||||||
|
if (isset($_REQUEST['displayRevoked'])) $this->displayRevoked = intval($_REQUEST['displayRevoked']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see wcf\page\IPage::assignVariables()
|
||||||
|
*/
|
||||||
|
public function assignVariables() {
|
||||||
|
parent::assignVariables();
|
||||||
|
|
||||||
|
WCF::getTPL()->assign(array(
|
||||||
|
'availableRooms' => \chat\data\room\RoomCache::getInstance()->getRooms(),
|
||||||
|
'roomID' => ($this->filterRoomID !== null) ? $this->filterRoomID : -1,
|
||||||
|
'username' => $this->filterUsername,
|
||||||
|
'issuerUsername' => $this->filterIssuerUsername,
|
||||||
|
'suspensionType' => $this->filterSuspensionType,
|
||||||
|
'userID' => $this->filterUserID,
|
||||||
|
'issuerUserID' => $this->filterIssuerUserID,
|
||||||
|
'displayRevoked' => $this->displayRevoked
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \wcf\page\MultipleLinkPage::readObjects()
|
||||||
|
*/
|
||||||
|
protected function initObjectList() {
|
||||||
|
parent::initObjectList();
|
||||||
|
|
||||||
|
$this->objectList->sqlSelects .= "user_table.username, user_table2.username AS issuerUsername, user_table3.username AS revokerUsername, room_table.title AS roomTitle";
|
||||||
|
$this->objectList->sqlJoins .= "
|
||||||
|
LEFT JOIN wcf".WCF_N."_user user_table
|
||||||
|
ON suspension.userID = user_table.userID
|
||||||
|
LEFT JOIN wcf".WCF_N."_user user_table2
|
||||||
|
ON suspension.issuer = user_table2.userID
|
||||||
|
LEFT JOIN wcf".WCF_N."_user user_table3
|
||||||
|
ON suspension.issuer = user_table3.userID";
|
||||||
|
$conditionJoins = " LEFT JOIN chat".WCF_N."_room room_table
|
||||||
|
ON suspension.roomID = room_table.roomID";
|
||||||
|
$this->objectList->sqlConditionJoins .= $conditionJoins;
|
||||||
|
$this->objectList->sqlJoins .= $conditionJoins;
|
||||||
|
|
||||||
|
if (!$this->displayRevoked) {
|
||||||
|
$this->objectList->getConditionBuilder()->add('expires > ?', array(TIME_NOW));
|
||||||
|
}
|
||||||
|
$this->objectList->getConditionBuilder()->add('(room_table.permanent = ? OR suspension.roomID IS NULL)', array(1));
|
||||||
|
if ($this->filterSuspensionType !== null) $this->objectList->getConditionBuilder()->add('suspension.type = ?', array($this->filterSuspensionType));
|
||||||
|
if ($this->filterUserID !== null) $this->objectList->getConditionBuilder()->add('suspension.userID = ?', array($this->filterUserID));
|
||||||
|
if ($this->filterIssuerUserID !== null) $this->objectList->getConditionBuilder()->add('suspension.issuer = ?', array($this->filterIssuerUserID));
|
||||||
|
if ($this->filterRoomID !== null) {
|
||||||
|
if ($this->filterRoomID === 0) {
|
||||||
|
$this->objectList->getConditionBuilder()->add('suspension.roomID IS NULL', array());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->objectList->getConditionBuilder()->add('suspension.roomID = ?', array($this->filterRoomID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,8 @@ class MessageList extends \wcf\data\DatabaseObjectList {
|
|||||||
* @return array<\chat\data\message\Message>
|
* @return array<\chat\data\message\Message>
|
||||||
*/
|
*/
|
||||||
public static function getNewestMessages(\chat\data\room\Room $room, $number = CHAT_LASTMESSAGES) {
|
public static function getNewestMessages(\chat\data\room\Room $room, $number = CHAT_LASTMESSAGES) {
|
||||||
|
if ($number === 0) return array();
|
||||||
|
|
||||||
$messageList = new static();
|
$messageList = new static();
|
||||||
$messageList->sqlOrderBy = "message.messageID DESC";
|
$messageList->sqlOrderBy = "message.messageID DESC";
|
||||||
$messageList->sqlLimit = $number;
|
$messageList->sqlLimit = $number;
|
||||||
|
@ -39,26 +39,33 @@ public function __toString() {
|
|||||||
public function canEnter(\wcf\data\user\User $user = null) {
|
public function canEnter(\wcf\data\user\User $user = null) {
|
||||||
if ($user === null) $user = WCF::getUser();
|
if ($user === null) $user = WCF::getUser();
|
||||||
if (!$user->userID) return false;
|
if (!$user->userID) return false;
|
||||||
|
$user = new \wcf\data\user\UserProfile($user);
|
||||||
|
|
||||||
$ph = new \chat\system\permission\PermissionHandler($user);
|
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
$suspensions = Suspension::getSuspensionsForUser($user);
|
if ($user->getPermission('mod.chat.canGban')) return true;
|
||||||
|
|
||||||
$canEnter = $ph->getPermission($this, 'user.canEnter');
|
$ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject());
|
||||||
|
if ($ph->getPermission($this, 'mod.canAlwaysEnter')) return true;
|
||||||
|
if ($ph->getPermission($this, 'mod.canBan')) return true;
|
||||||
|
|
||||||
|
if (!$ph->getPermission($this, 'user.canEnter')) return false;
|
||||||
|
|
||||||
|
$suspensions = Suspension::getSuspensionsForUser($user->getDecoratedObject());
|
||||||
// room suspension
|
// room suspension
|
||||||
if ($canEnter && isset($suspensions[$this->roomID][Suspension::TYPE_BAN])) {
|
if (isset($suspensions[$this->roomID][Suspension::TYPE_BAN])) {
|
||||||
if ($suspensions[$this->roomID][Suspension::TYPE_BAN]->isValid()) {
|
if ($suspensions[$this->roomID][Suspension::TYPE_BAN]->isValid()) {
|
||||||
$canEnter = false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// global suspension
|
// global suspension
|
||||||
if ($canEnter && isset($suspensions[null][Suspension::TYPE_BAN])) {
|
if (isset($suspensions[null][Suspension::TYPE_BAN])) {
|
||||||
if ($suspensions[null][Suspension::TYPE_BAN]->isValid()) {
|
if ($suspensions[null][Suspension::TYPE_BAN]->isValid()) {
|
||||||
$canEnter = false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $canEnter || $ph->getPermission($this, 'mod.canAlwaysEnter');
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,26 +77,33 @@ public function canEnter(\wcf\data\user\User $user = null) {
|
|||||||
public function canWrite(\wcf\data\user\User $user = null) {
|
public function canWrite(\wcf\data\user\User $user = null) {
|
||||||
if ($user === null) $user = WCF::getUser();
|
if ($user === null) $user = WCF::getUser();
|
||||||
if (!$user->userID) return false;
|
if (!$user->userID) return false;
|
||||||
|
$user = new \wcf\data\user\UserProfile($user);
|
||||||
|
|
||||||
$ph = new \chat\system\permission\PermissionHandler($user);
|
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
$suspensions = Suspension::getSuspensionsForUser($user);
|
if ($user->getPermission('mod.chat.canGmute')) return true;
|
||||||
|
|
||||||
$canWrite = $ph->getPermission($this, 'user.canWrite');
|
$ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject());
|
||||||
|
if ($ph->getPermission($this, 'mod.canAlwaysWrite')) return true;
|
||||||
|
if ($ph->getPermission($this, 'mod.canMute')) return true;
|
||||||
|
|
||||||
|
if (!$ph->getPermission($this, 'user.canWrite')) return false;
|
||||||
|
|
||||||
|
$suspensions = Suspension::getSuspensionsForUser($user->getDecoratedObject());
|
||||||
// room suspension
|
// room suspension
|
||||||
if ($canWrite && isset($suspensions[$this->roomID][Suspension::TYPE_MUTE])) {
|
if (isset($suspensions[$this->roomID][Suspension::TYPE_MUTE])) {
|
||||||
if ($suspensions[$this->roomID][Suspension::TYPE_MUTE]->isValid()) {
|
if ($suspensions[$this->roomID][Suspension::TYPE_MUTE]->isValid()) {
|
||||||
$canWrite = false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// global suspension
|
// global suspension
|
||||||
if ($canWrite && isset($suspensions[null][Suspension::TYPE_MUTE])) {
|
if (isset($suspensions[null][Suspension::TYPE_MUTE])) {
|
||||||
if ($suspensions[null][Suspension::TYPE_MUTE]->isValid()) {
|
if ($suspensions[null][Suspension::TYPE_MUTE]->isValid()) {
|
||||||
$canWrite = false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $canWrite || $ph->getPermission($this, 'mod.canAlwaysWrite');
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,21 +221,22 @@ public function join() {
|
|||||||
$messageAction->executeAction();
|
$messageAction->executeAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
$newestMessages = message\ViewableMessageList::getNewestMessages($room, CHAT_LASTMESSAGES);
|
$newestMessages = message\ViewableMessageList::getNewestMessages($room, CHAT_LASTMESSAGES + CHAT_DISPLAY_JOIN_LEAVE);
|
||||||
|
|
||||||
try {
|
// update last seen message
|
||||||
$lastSeen = end($newestMessages)->messageID;
|
$sql = "SELECT
|
||||||
}
|
MAX(messageID)
|
||||||
catch (\wcf\system\exception\SystemException $e) {
|
FROM
|
||||||
$lastSeen = 0;
|
chat".WCF_N."_message";
|
||||||
}
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
$editor = new \wcf\data\user\UserEditor($this->parameters['user']);
|
$editor = new \wcf\data\user\UserEditor($this->parameters['user']);
|
||||||
$editor->update(array(
|
$editor->update(array(
|
||||||
'chatRoomID' => $room->roomID,
|
'chatRoomID' => $room->roomID,
|
||||||
'chatAway' => null,
|
'chatAway' => null,
|
||||||
'chatLastActivity' => TIME_NOW,
|
'chatLastActivity' => TIME_NOW,
|
||||||
'chatLastSeen' => $lastSeen
|
'chatLastSeen' => $stmt->fetchColumn() ?: 0
|
||||||
));
|
));
|
||||||
|
|
||||||
// add activity points
|
// add activity points
|
||||||
|
@ -22,8 +22,8 @@ class Suspension extends \chat\data\CHATDatabaseObject {
|
|||||||
*/
|
*/
|
||||||
protected static $databaseTableIndexName = 'suspensionID';
|
protected static $databaseTableIndexName = 'suspensionID';
|
||||||
|
|
||||||
const TYPE_MUTE = 1;
|
const TYPE_MUTE = 'mute';
|
||||||
const TYPE_BAN = 2;
|
const TYPE_BAN = 'ban';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the suspension still is valid.
|
* Returns whether the suspension still is valid.
|
||||||
@ -34,6 +34,36 @@ public function isValid() {
|
|||||||
return $this->expires > TIME_NOW;
|
return $this->expires > TIME_NOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given user may view this suspension.
|
||||||
|
*
|
||||||
|
* @param \wcf\data\user\User $user
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isVisible($user = null) {
|
||||||
|
if ($user === null) $user = WCF::getUser();
|
||||||
|
$user = new \wcf\data\user\UserProfile($user);
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject());
|
||||||
|
|
||||||
|
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||||
|
if ($user->getPermission('mod.chat.canG'.$this->type)) return true;
|
||||||
|
if (!$this->roomID) return false;
|
||||||
|
if ($ph->getPermission($this->getRoom(), 'mod.can'.ucfirst($this->type))) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the room of this suspension.
|
||||||
|
*
|
||||||
|
* @return \chat\data\room\Room
|
||||||
|
*/
|
||||||
|
public function getRoom() {
|
||||||
|
if (!$this->roomID) return new \chat\data\room\Room(null, array('roomID' => null));
|
||||||
|
|
||||||
|
return \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the suspensions for the specified user (current user if no user was specified).
|
* Returns all the suspensions for the specified user (current user if no user was specified).
|
||||||
*
|
*
|
||||||
@ -53,15 +83,17 @@ public static function getSuspensionsForUser(\wcf\data\user\User $user = null) {
|
|||||||
if ($suspensions === false) throw new \wcf\system\exception\SystemException();
|
if ($suspensions === false) throw new \wcf\system\exception\SystemException();
|
||||||
}
|
}
|
||||||
catch (\wcf\system\exception\SystemException $e) {
|
catch (\wcf\system\exception\SystemException $e) {
|
||||||
|
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
|
||||||
|
$condition->add('userID = ?', array($user->userID));
|
||||||
|
$condition->add('expires > ?', array(TIME_NOW));
|
||||||
|
|
||||||
$sql = "SELECT
|
$sql = "SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
chat".WCF_N."_suspension
|
chat".WCF_N."_suspension
|
||||||
WHERE
|
".$condition;
|
||||||
userID = ?
|
|
||||||
AND expires > ?";
|
|
||||||
$stmt = WCF::getDB()->prepareStatement($sql);
|
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||||
$stmt->execute(array($user->userID, TIME_NOW));
|
$stmt->execute($condition->getParameters());
|
||||||
|
|
||||||
$suspensions = array();
|
$suspensions = array();
|
||||||
while ($suspension = $stmt->fetchObject('\chat\data\suspension\Suspension')) {
|
while ($suspension = $stmt->fetchObject('\chat\data\suspension\Suspension')) {
|
||||||
@ -76,7 +108,7 @@ public static function getSuspensionsForUser(\wcf\data\user\User $user = null) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the appropriate suspension for user, room and type.
|
* Returns the appropriate suspension for user, room and type.
|
||||||
* Returns false if no suspension was found.
|
* Returns false if no active suspension was found.
|
||||||
*
|
*
|
||||||
* @param \wcf\data\user\User $user
|
* @param \wcf\data\user\User $user
|
||||||
* @param \chat\data\room\Room $room
|
* @param \chat\data\room\Room $room
|
||||||
@ -84,23 +116,21 @@ public static function getSuspensionsForUser(\wcf\data\user\User $user = null) {
|
|||||||
* @return \chat\data\suspension\Suspension
|
* @return \chat\data\suspension\Suspension
|
||||||
*/
|
*/
|
||||||
public static function getSuspensionByUserRoomAndType(\wcf\data\user\User $user, \chat\data\room\Room $room, $type) {
|
public static function getSuspensionByUserRoomAndType(\wcf\data\user\User $user, \chat\data\room\Room $room, $type) {
|
||||||
|
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
|
||||||
|
$condition->add('userID = ?', array($user->userID));
|
||||||
|
$condition->add('type = ?', array($type));
|
||||||
|
$condition->add('expires > ?', array(TIME_NOW));
|
||||||
|
if ($room->roomID) $condition->add('roomID = ?', array($room->roomID));
|
||||||
|
else $condition->add('roomID IS NULL');
|
||||||
|
|
||||||
$sql = "SELECT
|
$sql = "SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
chat".WCF_N."_suspension
|
chat".WCF_N."_suspension
|
||||||
WHERE
|
".$condition;
|
||||||
userID = ?
|
|
||||||
AND type = ?";
|
|
||||||
|
|
||||||
$parameter = array($user->userID, $type);
|
|
||||||
if ($room->roomID) {
|
|
||||||
$sql .= " AND roomID = ?";
|
|
||||||
$parameter[] = $room->roomID;
|
|
||||||
}
|
|
||||||
else $sql .= " AND roomID IS NULL";
|
|
||||||
|
|
||||||
$statement = WCF::getDB()->prepareStatement($sql);
|
$statement = WCF::getDB()->prepareStatement($sql);
|
||||||
$statement->execute($parameter);
|
$statement->execute($condition->getParameters());
|
||||||
$row = $statement->fetchArray();
|
$row = $statement->fetchArray();
|
||||||
if (!$row) return false;
|
if (!$row) return false;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\data\suspension;
|
namespace chat\data\suspension;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes chat-suspension-related actions.
|
* Executes chat-suspension-related actions.
|
||||||
@ -17,23 +18,28 @@ class SuspensionAction extends \wcf\data\AbstractDatabaseObjectAction {
|
|||||||
protected $className = '\chat\data\suspension\SuspensionEditor';
|
protected $className = '\chat\data\suspension\SuspensionEditor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes expired suspensions.
|
* Validates permissions and parameters
|
||||||
*
|
|
||||||
* @return integer Number of deleted suspensions
|
|
||||||
*/
|
*/
|
||||||
public function prune() {
|
public function validateRevoke() {
|
||||||
$sql = "SELECT
|
WCF::getSession()->checkPermissions((array) 'admin.chat.canManageSuspensions');
|
||||||
".call_user_func(array($this->className, 'getDatabaseTableIndexName'))."
|
|
||||||
FROM
|
|
||||||
".call_user_func(array($this->className, 'getDatabaseTableName'))."
|
|
||||||
WHERE
|
|
||||||
expires < ?";
|
|
||||||
$stmt = \wcf\system\WCF::getDB()->prepareStatement($sql);
|
|
||||||
$stmt->execute(array(TIME_NOW));
|
|
||||||
$objectIDs = array();
|
|
||||||
|
|
||||||
while ($objectID = $stmt->fetchColumn()) $objectIDs[] = $objectID;
|
$this->parameters['revoker'] = WCF::getUser()->userID;
|
||||||
|
}
|
||||||
|
|
||||||
return call_user_func(array($this->className, 'deleteAll'), $objectIDs);
|
/**
|
||||||
|
* Revokes suspensions.
|
||||||
|
*/
|
||||||
|
public function revoke() {
|
||||||
|
if (!isset($this->parameters['revoker'])) {
|
||||||
|
$this->parameters['revoker'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$objectAction = new self($this->objectIDs, 'update', array(
|
||||||
|
'data' => array(
|
||||||
|
'expires' => TIME_NOW,
|
||||||
|
'revoker' => $this->parameters['revoker']
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$objectAction->executeAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
file/lib/data/suspension/SuspensionList.class.php
Normal file
18
file/lib/data/suspension/SuspensionList.class.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\data\suspension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a list of chat suspensions.
|
||||||
|
*
|
||||||
|
* @author Maximilian Mader
|
||||||
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage data.suspension
|
||||||
|
*/
|
||||||
|
class SuspensionList extends \wcf\data\DatabaseObjectList {
|
||||||
|
/**
|
||||||
|
* @see wcf\data\DatabaseObjectList::$className
|
||||||
|
*/
|
||||||
|
public $className = 'chat\data\suspension\Suspension';
|
||||||
|
}
|
@ -84,11 +84,14 @@ class ChatPage extends \wcf\page\AbstractPage {
|
|||||||
public function assignVariables() {
|
public function assignVariables() {
|
||||||
parent::assignVariables();
|
parent::assignVariables();
|
||||||
|
|
||||||
|
$reflection = new \ReflectionClass('\chat\data\message\Message');
|
||||||
|
|
||||||
WCF::getTPL()->assign(array(
|
WCF::getTPL()->assign(array(
|
||||||
'room' => $this->room,
|
'room' => $this->room,
|
||||||
'roomID' => $this->roomID,
|
'roomID' => $this->roomID,
|
||||||
'rooms' => $this->rooms,
|
'rooms' => $this->rooms,
|
||||||
'commands' => $this->commands,
|
'commands' => $this->commands,
|
||||||
|
'messageTypes' => $reflection->getConstants(),
|
||||||
'defaultSmilies' => $this->defaultSmilies,
|
'defaultSmilies' => $this->defaultSmilies,
|
||||||
'smileyCategories' => $this->smileyCategories,
|
'smileyCategories' => $this->smileyCategories,
|
||||||
'sidebarCollapsed' => \wcf\system\user\collapsible\content\UserCollapsibleContentHandler::getInstance()->isCollapsed('com.woltlab.wcf.collapsibleSidebar', 'be.bastelstu.chat.ChatPage'),
|
'sidebarCollapsed' => \wcf\system\user\collapsible\content\UserCollapsibleContentHandler::getInstance()->isCollapsed('com.woltlab.wcf.collapsibleSidebar', 'be.bastelstu.chat.ChatPage'),
|
||||||
|
@ -106,10 +106,7 @@ public function show() {
|
|||||||
parent::show();
|
parent::show();
|
||||||
|
|
||||||
@header('Content-type: application/json');
|
@header('Content-type: application/json');
|
||||||
// enable gzip compression
|
\wcf\util\HeaderUtil::sendNoCacheHeaders();
|
||||||
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());
|
$json = array('users' => array(), 'messages' => array());
|
||||||
|
|
||||||
|
126
file/lib/system/command/AbstractSuspensionCommand.class.php
Normal file
126
file/lib/system/command/AbstractSuspensionCommand.class.php
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \chat\data\suspension;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for suspension commands
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
abstract class AbstractSuspensionCommand extends AbstractRestrictedCommand {
|
||||||
|
public $user = null;
|
||||||
|
public $expires = 0;
|
||||||
|
public $suspensionAction = null;
|
||||||
|
public $link = '';
|
||||||
|
public $room = null;
|
||||||
|
public $reason = '';
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$parameters = explode(',', $commandHandler->getParameters(), 3);
|
||||||
|
list($username, $modifier) = $parameters;
|
||||||
|
|
||||||
|
if (isset($parameters[2])) {
|
||||||
|
$this->reason = \wcf\util\StringUtil::trim($parameters[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$modifier = ChatUtil::timeModifier(\wcf\util\StringUtil::trim($modifier));
|
||||||
|
$expires = strtotime($modifier, TIME_NOW);
|
||||||
|
$this->expires = min(max(-0x80000000, $expires), 0x7FFFFFFF);
|
||||||
|
}
|
||||||
|
catch (\wcf\system\exception\SystemException $e) {
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $this->user
|
||||||
|
));
|
||||||
|
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
||||||
|
|
||||||
|
$this->executeAction();
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function executeAction() {
|
||||||
|
if (static::IS_GLOBAL) $room = new \chat\data\room\Room(null, array('roomID' => null));
|
||||||
|
else $room = $this->room;
|
||||||
|
|
||||||
|
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, static::SUSPENSION_TYPE)) {
|
||||||
|
if ($suspension->expires >= $this->expires) {
|
||||||
|
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.exists'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = new suspension\SuspensionAction(array($suspension), 'revoke', array(
|
||||||
|
'revoker' => WCF::getUser()->userID
|
||||||
|
));
|
||||||
|
$action->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->suspensionAction = new suspension\SuspensionAction(array(), 'create', array(
|
||||||
|
'data' => array(
|
||||||
|
'userID' => $this->user->userID,
|
||||||
|
'roomID' => $room->roomID ?: null,
|
||||||
|
'type' => static::SUSPENSION_TYPE,
|
||||||
|
'expires' => $this->expires,
|
||||||
|
'time' => TIME_NOW,
|
||||||
|
'issuer' => WCF::getUser()->userID,
|
||||||
|
'reason' => $this->reason
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$this->suspensionAction->executeAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
$this->room = $this->commandHandler->getRoom();
|
||||||
|
if (WCF::getSession()->getPermission('admin.chat.canManageSuspensions')) return;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler();
|
||||||
|
if (static::IS_GLOBAL) {
|
||||||
|
WCF::getSession()->checkPermissions((array) 'mod.chat.canG'.static::SUSPENSION_TYPE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!WCF::getSession()->getPermission('mod.chat.canG'.static::SUSPENSION_TYPE)) {
|
||||||
|
if (!$ph->getPermission($this->room, 'mod.can'.ucfirst(static::SUSPENSION_TYPE))) {
|
||||||
|
throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_MODERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return serialize(array(
|
||||||
|
'link' => $this->link,
|
||||||
|
'expires' => $this->expires,
|
||||||
|
'type' => (static::IS_GLOBAL ? 'g' : '').static::SUSPENSION_TYPE,
|
||||||
|
'reason' => $this->reason
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command;
|
||||||
|
use \chat\data\suspension;
|
||||||
|
use \chat\util\ChatUtil;
|
||||||
|
use \wcf\data\user\User;
|
||||||
|
use \wcf\system\WCF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for suspension commands
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command
|
||||||
|
*/
|
||||||
|
abstract class AbstractUnsuspensionCommand extends AbstractRestrictedCommand {
|
||||||
|
public $user = null;
|
||||||
|
public $suspensionAction = null;
|
||||||
|
public $link = '';
|
||||||
|
public $room = null;
|
||||||
|
|
||||||
|
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
||||||
|
parent::__construct($commandHandler);
|
||||||
|
|
||||||
|
$username = rtrim($commandHandler->getParameters(), ',');
|
||||||
|
$this->user = User::getUserByUsername($username);
|
||||||
|
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
||||||
|
|
||||||
|
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
||||||
|
'object' => $this->user
|
||||||
|
));
|
||||||
|
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
||||||
|
|
||||||
|
$this->executeAction();
|
||||||
|
|
||||||
|
$this->didInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function executeAction() {
|
||||||
|
if (static::IS_GLOBAL) $room = new \chat\data\room\Room(null, array('roomID' => null));
|
||||||
|
else $room = $this->room;
|
||||||
|
|
||||||
|
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, static::SUSPENSION_TYPE)) {
|
||||||
|
$action = new suspension\SuspensionAction(array($suspension), 'revoke', array(
|
||||||
|
'revoker' => WCF::getUser()->userID
|
||||||
|
));
|
||||||
|
$action->executeAction();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.notExists'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
||||||
|
*/
|
||||||
|
public function checkPermission() {
|
||||||
|
parent::checkPermission();
|
||||||
|
|
||||||
|
$this->room = $this->commandHandler->getRoom();
|
||||||
|
if (WCF::getSession()->getPermission('admin.chat.canManageSuspensions')) return;
|
||||||
|
|
||||||
|
$ph = new \chat\system\permission\PermissionHandler();
|
||||||
|
if (static::IS_GLOBAL) {
|
||||||
|
WCF::getSession()->checkPermission((array) 'mod.chat.canG'.static::SUSPENSION_TYPE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!WCF::getSession()->getPermission('mod.chat.canG'.static::SUSPENSION_TYPE)) {
|
||||||
|
if (!$ph->getPermission($this->room, 'mod.can'.ucfirst(static::SUSPENSION_TYPE))) {
|
||||||
|
throw new \wcf\system\exception\PermissionDeniedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getType()
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return \chat\data\message\Message::TYPE_MODERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \chat\system\command\ICommand::getMessage()
|
||||||
|
*/
|
||||||
|
public function getMessage() {
|
||||||
|
return serialize(array(
|
||||||
|
'link' => $this->link,
|
||||||
|
'type' => 'un'.(static::IS_GLOBAL ? 'g' : '').static::SUSPENSION_TYPE,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -36,11 +36,4 @@ public function getType() {
|
|||||||
public function getMessage() {
|
public function getMessage() {
|
||||||
return \wcf\system\bbcode\PreParser::getInstance()->parse($this->commandHandler->getParameters(), explode(',', WCF::getSession()->getPermission('user.chat.allowedBBCodes')));
|
return \wcf\system\bbcode\PreParser::getInstance()->parse($this->commandHandler->getParameters(), explode(',', WCF::getSession()->getPermission('user.chat.allowedBBCodes')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\ICommand::getReceiver()
|
|
||||||
*/
|
|
||||||
public function getReceiver() {
|
|
||||||
return WCF::getUser()->userID;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\system\command\commands;
|
namespace chat\system\command\commands;
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bans a user.
|
* Bans a user.
|
||||||
@ -14,25 +10,7 @@
|
|||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
* @subpackage system.chat.command.commands
|
* @subpackage system.chat.command.commands
|
||||||
*/
|
*/
|
||||||
class BanCommand extends MuteCommand {
|
class BanCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
public function executeAction() {
|
const IS_GLOBAL = false;
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $this->room, suspension\Suspension::TYPE_BAN)) {
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
if ($suspension->expires > $this->expires) {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.exists'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->suspensionAction = new suspension\SuspensionAction(array(), 'create', array(
|
|
||||||
'data' => array(
|
|
||||||
'userID' => $this->user->userID,
|
|
||||||
'roomID' => WCF::getUser()->chatRoomID,
|
|
||||||
'type' => suspension\Suspension::TYPE_BAN,
|
|
||||||
'expires' => $this->expires
|
|
||||||
)
|
|
||||||
));
|
|
||||||
$this->suspensionAction->executeAction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\system\command\commands;
|
namespace chat\system\command\commands;
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globally bans a user.
|
* Globally bans a user.
|
||||||
@ -14,27 +10,7 @@
|
|||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
* @subpackage system.chat.command.commands
|
* @subpackage system.chat.command.commands
|
||||||
*/
|
*/
|
||||||
class GbanCommand extends MuteCommand {
|
class GbanCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
public function executeAction() {
|
const IS_GLOBAL = true;
|
||||||
$room = new \chat\data\room\Room(null, array('roomID' => null));
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, suspension\Suspension::TYPE_BAN)) {
|
|
||||||
if ($suspension->expires > $this->expires) {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.exists'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->suspensionAction = new suspension\SuspensionAction(array(), 'create', array(
|
|
||||||
'data' => array(
|
|
||||||
'userID' => $this->user->userID,
|
|
||||||
'roomID' => null,
|
|
||||||
'type' => suspension\Suspension::TYPE_BAN,
|
|
||||||
'expires' => $this->expires
|
|
||||||
)
|
|
||||||
));
|
|
||||||
$this->suspensionAction->executeAction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\system\command\commands;
|
namespace chat\system\command\commands;
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globally bans a user.
|
* Globally mutes a user.
|
||||||
*
|
*
|
||||||
* @author Tim Düsterhus
|
* @author Tim Düsterhus
|
||||||
* @copyright 2010-2013 Tim Düsterhus
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
@ -14,27 +10,7 @@
|
|||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
* @subpackage system.chat.command.commands
|
* @subpackage system.chat.command.commands
|
||||||
*/
|
*/
|
||||||
class GmuteCommand extends MuteCommand {
|
class GmuteCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
public function executeAction() {
|
const IS_GLOBAL = true;
|
||||||
$room = new \chat\data\room\Room(null, array('roomID' => null));
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||||
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, suspension\Suspension::TYPE_MUTE)) {
|
|
||||||
if ($suspension->expires > $this->expires) {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.exists'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->suspensionAction = new suspension\SuspensionAction(array(), 'create', array(
|
|
||||||
'data' => array(
|
|
||||||
'userID' => $this->user->userID,
|
|
||||||
'roomID' => null,
|
|
||||||
'type' => suspension\Suspension::TYPE_MUTE,
|
|
||||||
'expires' => $this->expires
|
|
||||||
)
|
|
||||||
));
|
|
||||||
$this->suspensionAction->executeAction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace chat\system\command\commands;
|
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unbans a user globally.
|
|
||||||
*
|
|
||||||
* @author Tim Düsterhus
|
|
||||||
* @copyright 2010-2013 Tim Düsterhus
|
|
||||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
|
||||||
* @package be.bastelstu.chat
|
|
||||||
* @subpackage system.chat.command.commands
|
|
||||||
*/
|
|
||||||
class GunbanCommand extends UnmuteCommand {
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\commands\UnmuteCommand::executeAction()
|
|
||||||
*/
|
|
||||||
public function executeAction() {
|
|
||||||
$room = new \chat\data\room\Room(null, array('roomID' => null));
|
|
||||||
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, suspension\Suspension::TYPE_BAN)) {
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.notExists'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace chat\system\command\commands;
|
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unmutes a user globally.
|
|
||||||
*
|
|
||||||
* @author Tim Düsterhus
|
|
||||||
* @copyright 2010-2013 Tim Düsterhus
|
|
||||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
|
||||||
* @package be.bastelstu.chat
|
|
||||||
* @subpackage system.chat.command.commands
|
|
||||||
*/
|
|
||||||
class GunmuteCommand extends UnmuteCommand {
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\commands\UnmuteCommand::executeAction()
|
|
||||||
*/
|
|
||||||
public function executeAction() {
|
|
||||||
$room = new \chat\data\room\Room(null, array('roomID' => null));
|
|
||||||
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $room, suspension\Suspension::TYPE_MUTE)) {
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.notExists'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -45,11 +45,11 @@ public function __construct(\chat\system\command\CommandHandler $commandHandler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Suspensions
|
// Suspensions
|
||||||
// TODO: Permissions
|
|
||||||
$suspensions = \chat\data\suspension\Suspension::getSuspensionsForUser($this->user);
|
$suspensions = \chat\data\suspension\Suspension::getSuspensionsForUser($this->user);
|
||||||
foreach ($suspensions as $roomSuspensions) {
|
foreach ($suspensions as $roomSuspensions) {
|
||||||
foreach ($roomSuspensions as $typeSuspension) {
|
foreach ($roomSuspensions as $typeSuspension) {
|
||||||
if (!$typeSuspension->isValid()) continue;
|
if (!$typeSuspension->isValid()) continue;
|
||||||
|
if (!$typeSuspension->isVisible()) continue;
|
||||||
|
|
||||||
$dateTime = DateUtil::getDateTimeByTimestamp($typeSuspension->expires);
|
$dateTime = DateUtil::getDateTimeByTimestamp($typeSuspension->expires);
|
||||||
$name = WCF::getLanguage()->getDynamicVariable('chat.general.information.suspension', array(
|
$name = WCF::getLanguage()->getDynamicVariable('chat.general.information.suspension', array(
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\system\command\commands;
|
namespace chat\system\command\commands;
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutes a user.
|
* Mutes a user.
|
||||||
@ -14,86 +10,7 @@
|
|||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
* @subpackage system.chat.command.commands
|
* @subpackage system.chat.command.commands
|
||||||
*/
|
*/
|
||||||
class MuteCommand extends \chat\system\command\AbstractRestrictedCommand {
|
class MuteCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||||
public $user = null;
|
const IS_GLOBAL = false;
|
||||||
public $expires = 0;
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||||
public $suspensionAction = null;
|
|
||||||
public $link = '';
|
|
||||||
public $room = null;
|
|
||||||
|
|
||||||
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
|
||||||
parent::__construct($commandHandler);
|
|
||||||
|
|
||||||
try {
|
|
||||||
list($username, $modifier) = explode(',', $commandHandler->getParameters(), 2);
|
|
||||||
$modifier = ChatUtil::timeModifier(\wcf\util\StringUtil::trim($modifier));
|
|
||||||
$expires = strtotime($modifier, TIME_NOW);
|
|
||||||
$this->expires = min(max(-0x80000000, $expires), 0x7FFFFFFF);
|
|
||||||
}
|
|
||||||
catch (\wcf\system\exception\SystemException $e) {
|
|
||||||
throw new \InvalidArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->user = User::getUserByUsername($username);
|
|
||||||
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
|
||||||
|
|
||||||
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
|
||||||
'object' => $this->user
|
|
||||||
));
|
|
||||||
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
|
||||||
|
|
||||||
$this->executeAction();
|
|
||||||
|
|
||||||
$this->didInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function executeAction() {
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $this->room, suspension\Suspension::TYPE_MUTE)) {
|
|
||||||
if ($suspension->expires > $this->expires) {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.exists'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->suspensionAction = new suspension\SuspensionAction(array(), 'create', array(
|
|
||||||
'data' => array(
|
|
||||||
'userID' => $this->user->userID,
|
|
||||||
'roomID' => WCF::getUser()->chatRoomID,
|
|
||||||
'type' => suspension\Suspension::TYPE_MUTE,
|
|
||||||
'expires' => $this->expires
|
|
||||||
)
|
|
||||||
));
|
|
||||||
$this->suspensionAction->executeAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
|
||||||
*/
|
|
||||||
public function checkPermission() {
|
|
||||||
parent::checkPermission();
|
|
||||||
|
|
||||||
$this->room = $this->commandHandler->getRoom();
|
|
||||||
$ph = new \chat\system\permission\PermissionHandler();
|
|
||||||
if (!$ph->getPermission($this->room, 'mod.can'.str_replace(array('chat\system\command\commands\\', 'Command'), '', get_class($this)))) throw new \wcf\system\exception\PermissionDeniedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\ICommand::getType()
|
|
||||||
*/
|
|
||||||
public function getType() {
|
|
||||||
return \chat\data\message\Message::TYPE_MODERATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\ICommand::getMessage()
|
|
||||||
*/
|
|
||||||
public function getMessage() {
|
|
||||||
return serialize(array(
|
|
||||||
'link' => $this->link,
|
|
||||||
'expires' => $this->expires,
|
|
||||||
'type' => str_replace(array('chat\system\command\commands\\', 'command'), '', strtolower(get_class($this)))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\system\command\commands;
|
namespace chat\system\command\commands;
|
||||||
use \chat\data\suspension;
|
|
||||||
use \chat\util\ChatUtil;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bans a user.
|
* Bans a user.
|
||||||
@ -14,17 +10,7 @@
|
|||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
* @subpackage system.chat.command.commands
|
* @subpackage system.chat.command.commands
|
||||||
*/
|
*/
|
||||||
class UnbanCommand extends UnmuteCommand {
|
class UnbanCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||||
/**
|
const IS_GLOBAL = false;
|
||||||
* @see \chat\system\command\commands\UnmuteCommand::executeAction()
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
*/
|
|
||||||
public function executeAction() {
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $this->room, suspension\Suspension::TYPE_BAN)) {
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.notExists'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
16
file/lib/system/command/commands/UngbanCommand.class.php
Normal file
16
file/lib/system/command/commands/UngbanCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbans a user globally.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class UngbanCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||||
|
const IS_GLOBAL = true;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||||
|
}
|
16
file/lib/system/command/commands/UngmuteCommand.class.php
Normal file
16
file/lib/system/command/commands/UngmuteCommand.class.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
namespace chat\system\command\commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmutes a user globally.
|
||||||
|
*
|
||||||
|
* @author Tim Düsterhus
|
||||||
|
* @copyright 2010-2013 Tim Düsterhus
|
||||||
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
|
* @package be.bastelstu.chat
|
||||||
|
* @subpackage system.chat.command.commands
|
||||||
|
*/
|
||||||
|
class UngmuteCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||||
|
const IS_GLOBAL = true;
|
||||||
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||||
|
}
|
@ -1,8 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace chat\system\command\commands;
|
namespace chat\system\command\commands;
|
||||||
use \chat\data\suspension;
|
|
||||||
use \wcf\data\user\User;
|
|
||||||
use \wcf\system\WCF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmutes a user.
|
* Unmutes a user.
|
||||||
@ -13,67 +10,7 @@
|
|||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
* @subpackage system.chat.command.commands
|
* @subpackage system.chat.command.commands
|
||||||
*/
|
*/
|
||||||
class UnmuteCommand extends \chat\system\command\AbstractRestrictedCommand {
|
class UnmuteCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||||
public $user = null;
|
const IS_GLOBAL = false;
|
||||||
public $suspensionAction = null;
|
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||||
public $link = '';
|
|
||||||
public $room = null;
|
|
||||||
|
|
||||||
public function __construct(\chat\system\command\CommandHandler $commandHandler) {
|
|
||||||
parent::__construct($commandHandler);
|
|
||||||
|
|
||||||
$username = rtrim($commandHandler->getParameters(), ',');
|
|
||||||
$this->user = User::getUserByUsername($username);
|
|
||||||
if (!$this->user->userID) throw new \chat\system\command\UserNotFoundException($username);
|
|
||||||
|
|
||||||
$profile = \wcf\system\request\LinkHandler::getInstance()->getLink('User', array(
|
|
||||||
'object' => $this->user
|
|
||||||
));
|
|
||||||
$this->link = "[url='".$profile."']".$this->user->username.'[/url]';
|
|
||||||
|
|
||||||
$this->executeAction();
|
|
||||||
|
|
||||||
$this->didInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the suspension.
|
|
||||||
*/
|
|
||||||
public function executeAction() {
|
|
||||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $this->room, suspension\Suspension::TYPE_MUTE)) {
|
|
||||||
$action = new suspension\SuspensionAction(array($suspension), 'delete');
|
|
||||||
$action->executeAction();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new \wcf\system\exception\UserInputException('text', WCF::getLanguage()->get('wcf.chat.suspension.notExists'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\IRestrictedChatCommand::checkPermission()
|
|
||||||
*/
|
|
||||||
public function checkPermission() {
|
|
||||||
parent::checkPermission();
|
|
||||||
|
|
||||||
$this->room = $this->commandHandler->getRoom();
|
|
||||||
$ph = new \chat\system\permission\PermissionHandler();
|
|
||||||
if (!$ph->getPermission($this->room, 'mod.can'.ucfirst(str_replace(array('chat\system\command\commands\\Un', 'Command'), '', get_class($this))))) throw new \wcf\system\exception\PermissionDeniedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\ICommand::getType()
|
|
||||||
*/
|
|
||||||
public function getType() {
|
|
||||||
return \chat\data\message\Message::TYPE_MODERATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \chat\system\command\ICommand::getMessage()
|
|
||||||
*/
|
|
||||||
public function getMessage() {
|
|
||||||
return serialize(array(
|
|
||||||
'link' => $this->link,
|
|
||||||
'type' => str_replace(array('chat\system\command\commands\\', 'command'), '', strtolower(get_class($this)))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ public function execute(\wcf\data\cronjob\Cronjob $cronjob) {
|
|||||||
$messageAction->executeAction();
|
$messageAction->executeAction();
|
||||||
$roomAction = new data\room\RoomAction(array(), 'prune');
|
$roomAction = new data\room\RoomAction(array(), 'prune');
|
||||||
$roomAction->executeAction();
|
$roomAction->executeAction();
|
||||||
$suspensionAction = new data\suspension\SuspensionAction(array(), 'prune');
|
|
||||||
$suspensionAction->executeAction();
|
|
||||||
|
|
||||||
// kill dead users
|
// kill dead users
|
||||||
$roomAction = new data\room\RoomAction(array(), 'removeDeadUsers');
|
$roomAction = new data\room\RoomAction(array(), 'removeDeadUsers');
|
||||||
|
@ -16,6 +16,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.__bubbleArrow {
|
||||||
|
border-color: transparent @wcfContainerBorderColor;
|
||||||
|
left: -6px;
|
||||||
|
top: 5px;
|
||||||
|
border-width: 6px 6px 6px 0;
|
||||||
|
border-style: solid;
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#tplChat {
|
#tplChat {
|
||||||
#main > div {
|
#main > div {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -28,17 +40,120 @@
|
|||||||
.transition(padding-top, .2s);
|
.transition(padding-top, .2s);
|
||||||
.transition(padding-bottom, .2s);
|
.transition(padding-bottom, .2s);
|
||||||
|
|
||||||
&.empty {
|
&.empty, &.hidden {
|
||||||
height: 0px;
|
height: 0px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
||||||
|
~ #timsChatMessageContainer {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jsTopicCloser {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#privateChannelsMenu {
|
||||||
|
.transition(opacity, .2s);
|
||||||
|
.marginTop;
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&.shown {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 130;
|
||||||
|
|
||||||
|
~ .timsChatMessageContainer {
|
||||||
|
margin-left: 35px;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
> li:first-child {
|
||||||
|
> .userAvatar.framed {
|
||||||
|
img, > canvas, > .icon {
|
||||||
|
border-radius: @wcfContainerBorderRadius 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> li:last-child {
|
||||||
|
> .userAvatar.framed {
|
||||||
|
img, > canvas, > .icon {
|
||||||
|
border-radius: 0 0 0 @wcfContainerBorderRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> li {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
background-color: @wcfContainerBackgroundColor;
|
||||||
|
|
||||||
|
> .userAvatar, .userAvatar > .icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .userAvatar {
|
||||||
|
&.large {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.framed {
|
||||||
|
> .icon {
|
||||||
|
background-color: @wcfContentBackgroundColor;
|
||||||
|
border: 1px solid @wcfContainerBorderColor;
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
> .userAvatar {
|
||||||
|
&.large {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.framed {
|
||||||
|
> img, > canvas, > .icon {
|
||||||
|
border-right-color: @wcfContentBackgroundColor;
|
||||||
|
|
||||||
|
border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.notify {
|
||||||
|
> .userAvatar {
|
||||||
|
> * {
|
||||||
|
// TODO
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.timsChatMessageContainer {
|
.timsChatMessageContainer {
|
||||||
height: 200px;
|
height: 320px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
display: none;
|
display: none;
|
||||||
@ -55,9 +170,9 @@
|
|||||||
color: @wcfSelectedColor;
|
color: @wcfSelectedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
> {
|
> .innerMessageContainer {
|
||||||
.markContainer {
|
.markContainer {
|
||||||
display: table-cell;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,47 +192,138 @@
|
|||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::before {
|
|
||||||
.icon;
|
|
||||||
.icon16;
|
|
||||||
padding: @wcfGapTiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(even) {
|
&:nth-child(even) {
|
||||||
|
> .innerMessageContainer.bubble .innerMessage, .innerMessageContainer.right.bubble .innerMessage {
|
||||||
background-color: @wcfContainerAccentBackgroundColor;
|
background-color: @wcfContainerAccentBackgroundColor;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-color: transparent @wcfContainerAccentBackgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> {
|
.messageIcon {
|
||||||
time, .usernameContainer, .text, .markContainer {
|
float: left;
|
||||||
display: table-cell;
|
padding: 8px 0 0 4px;
|
||||||
vertical-align: top;
|
margin-right: -16px;
|
||||||
padding: @wcfGapTiny 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.markContainer {
|
> .innerMessageContainer {
|
||||||
display: none;
|
padding: 5px 20px 5px 5px;
|
||||||
padding: 0;
|
position: relative;
|
||||||
|
|
||||||
|
.userAvatar {
|
||||||
|
float: left;
|
||||||
|
margin-left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.innerMessage {
|
||||||
|
margin-left: 46px;
|
||||||
|
padding: 2px 5px 5px;
|
||||||
|
|
||||||
time {
|
time {
|
||||||
&::before {
|
float: right;
|
||||||
content: "[";
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
img {
|
||||||
|
max-width: 480px;
|
||||||
|
max-height: 320px;
|
||||||
}
|
}
|
||||||
&::after {
|
|
||||||
content: "]";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.usernameContainer {
|
&.bubble {
|
||||||
text-align: right;
|
.userAvatar {
|
||||||
min-width: 100px;
|
margin-left: 0;
|
||||||
padding-right: @wcfGapSmall;
|
|
||||||
white-space: nowrap;
|
.icon {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerMessage {
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: @wcfContainerBorderColor;
|
||||||
|
border-radius: @wcfContainerBorderRadius;
|
||||||
|
background-color: @wcfContainerBackgroundColor;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.username {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
> ul.text {
|
||||||
width: 100%;
|
li {
|
||||||
|
.clearfix;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
border-color: @wcfContainerBorderColor;
|
||||||
|
padding: 3px 0 4px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-style: none;
|
||||||
|
padding: 3px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
.__bubbleArrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
.__bubbleArrow;
|
||||||
|
border-color: transparent @wcfContainerBackgroundColor;
|
||||||
|
left: -5px;
|
||||||
|
top: 6px;
|
||||||
|
border-width: 5px 5px 5px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
.userAvatar {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerMessage {
|
||||||
|
margin-right: 46px;
|
||||||
|
margin-left: 0px;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
.__bubbleArrow;
|
||||||
|
left: auto;
|
||||||
|
right: -6px;
|
||||||
|
border-width: 6px 0 6px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
.__bubbleArrow;
|
||||||
|
border-color: transparent @wcfContainerBackgroundColor;
|
||||||
|
left: auto;
|
||||||
|
right: -5px;
|
||||||
|
top: 6px;
|
||||||
|
border-width: 5px 0 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
time {
|
||||||
|
float: left;
|
||||||
|
margin-right: @wcfGapTiny;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .markContainer {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
top: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
install.sql
12
install.sql
@ -46,10 +46,14 @@ CREATE TABLE chat1_suspension (
|
|||||||
suspensionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
suspensionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
userID INT(10) NOT NULL,
|
userID INT(10) NOT NULL,
|
||||||
roomID INT(10) DEFAULT NULL,
|
roomID INT(10) DEFAULT NULL,
|
||||||
type TINYINT(3) NOT NULL,
|
type VARCHAR(15) NOT NULL,
|
||||||
expires INT(10) NOT NULL,
|
expires INT(10) NOT NULL,
|
||||||
|
time INT(10) NOT NULL,
|
||||||
|
issuer INT(10) DEFAULT NULL,
|
||||||
|
reason VARCHAR(255) NOT NULL DEFAULT '',
|
||||||
|
revoker INT(10) DEFAULT NULL,
|
||||||
|
|
||||||
UNIQUE KEY suspension (userID, roomID, type),
|
KEY suspension (userID, roomID, type),
|
||||||
KEY (roomID),
|
KEY (roomID),
|
||||||
KEY (type),
|
KEY (type),
|
||||||
KEY (expires)
|
KEY (expires)
|
||||||
@ -70,10 +74,12 @@ ALTER TABLE chat1_room ADD FOREIGN KEY (owner) REFERENCES wcf1_user (userID) ON
|
|||||||
|
|
||||||
ALTER TABLE chat1_suspension ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
|
ALTER TABLE chat1_suspension ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
|
||||||
ALTER TABLE chat1_suspension ADD FOREIGN KEY (roomID) REFERENCES chat1_room (roomID) ON DELETE CASCADE;
|
ALTER TABLE chat1_suspension ADD FOREIGN KEY (roomID) REFERENCES chat1_room (roomID) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE chat1_suspension ADD FOREIGN KEY (issuer) REFERENCES wcf1_user (userID) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE chat1_suspension ADD FOREIGN KEY (revoker) REFERENCES wcf1_user (userID) ON DELETE SET NULL;
|
||||||
|
|
||||||
ALTER TABLE wcf1_user ADD FOREIGN KEY (chatRoomID) REFERENCES chat1_room (roomID) ON DELETE SET NULL;
|
ALTER TABLE wcf1_user ADD FOREIGN KEY (chatRoomID) REFERENCES chat1_room (roomID) ON DELETE SET NULL;
|
||||||
|
|
||||||
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('chat.room.title1', 'chat.room.topic1', 1);
|
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('chat.room.title1', 'chat.room.topic1', 1);
|
||||||
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('Testroom 2', 'Topic of Testroom 2', 2);
|
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('Testroom 2', 'Topic of Testroom 2', 2);
|
||||||
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('Testroom with a very long', 'The topic of this room is rather loing as well!', 3);
|
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('Testroom with a very long name', 'The topic of this room is rather loing as well!', 3);
|
||||||
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('Room w/o topic', '', 4);
|
INSERT INTO chat1_room (title, topic, showOrder) VALUES ('Room w/o topic', '', 4);
|
||||||
|
@ -11,10 +11,32 @@
|
|||||||
<item name="chat.acp.room.delete.sure"><![CDATA[Wollen Sie den Raum „{$chatRoom}“ wirklich löschen?]]></item>
|
<item name="chat.acp.room.delete.sure"><![CDATA[Wollen Sie den Raum „{$chatRoom}“ wirklich löschen?]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
|
<category name="chat.acp.suspension">
|
||||||
|
<item name="chat.acp.suspension.list"><![CDATA[Sanktionen]]></item>
|
||||||
|
<item name="chat.acp.suspension.type"><![CDATA[Art der Sanktion]]></item>
|
||||||
|
<item name="chat.acp.suspension.issuer"><![CDATA[Aussteller]]></item>
|
||||||
|
<item name="chat.acp.suspension.displayRevoked"><![CDATA[Abgelaufene Sanktionen anzeigen]]></item>
|
||||||
|
<item name="chat.acp.suspension.reason"><![CDATA[Grund]]></item>
|
||||||
|
<item name="chat.acp.suspension.revoked"><![CDATA[Zurückziehen]]></item>
|
||||||
|
<item name="chat.acp.suspension.revokedBy"><![CDATA[Zurückgezogen von {$suspension->revokerUsername}]]></item>
|
||||||
|
</category>
|
||||||
|
|
||||||
<category name="chat.acp.menu">
|
<category name="chat.acp.menu">
|
||||||
<item name="chat.acp.menu.link"><![CDATA[Chat]]></item>
|
<item name="chat.acp.menu.link"><![CDATA[Chat]]></item>
|
||||||
<item name="chat.acp.menu.link.room.list"><![CDATA[Chaträume auflisten]]></item>
|
<item name="chat.acp.menu.link.room.list"><![CDATA[Chaträume auflisten]]></item>
|
||||||
<item name="chat.acp.menu.link.room.add"><![CDATA[Chatraum hinzufügen]]></item>
|
<item name="chat.acp.menu.link.room.add"><![CDATA[Chatraum hinzufügen]]></item>
|
||||||
|
<item name="chat.acp.menu.link.suspension.list"><![CDATA[Sanktionen auflisten]]></item>
|
||||||
|
</category>
|
||||||
|
|
||||||
|
<category name="wcf.acl.option">
|
||||||
|
<item name="wcf.acl.option.category.be.bastelstu.chat.room.user"><![CDATA[Benutzerrechte]]></item>
|
||||||
|
<item name="wcf.acl.option.category.be.bastelstu.chat.room.mod"><![CDATA[Moderative Rechte]]></item>
|
||||||
|
<item name="wcf.acl.option.be.bastelstu.chat.room.user.canEnter"><![CDATA[Kann Raum betreten]]></item>
|
||||||
|
<item name="wcf.acl.option.be.bastelstu.chat.room.user.canWrite"><![CDATA[Kann schreiben]]></item>
|
||||||
|
<item name="wcf.acl.option.be.bastelstu.chat.room.mod.canAlwaysEnter"><![CDATA[Kann Raum immer betreten]]></item>
|
||||||
|
<item name="wcf.acl.option.be.bastelstu.chat.room.mod.canAlwaysWrite"><![CDATA[Kann immer schreiben]]></item>
|
||||||
|
<item name="wcf.acl.option.be.bastelstu.chat.room.mod.canMute"><![CDATA[Kann knebeln]]></item>
|
||||||
|
<item name="wcf.acl.option.be.bastelstu.chat.room.mod.canBan"><![CDATA[Kann bannen]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="wcf.acp.group">
|
<category name="wcf.acp.group">
|
||||||
@ -24,12 +46,24 @@
|
|||||||
<item name="wcf.acp.group.option.user.chat.canTempRoom"><![CDATA[Kann temporäre Räume erstellen]]></item>
|
<item name="wcf.acp.group.option.user.chat.canTempRoom"><![CDATA[Kann temporäre Räume erstellen]]></item>
|
||||||
|
|
||||||
<item name="wcf.acp.group.option.category.mod.chat"><![CDATA[Chat]]></item>
|
<item name="wcf.acp.group.option.category.mod.chat"><![CDATA[Chat]]></item>
|
||||||
<item name="wcf.acp.group.option.mod.chat.canAlwaysEnter"><![CDATA[Kann jeden Raum betreten]]></item>
|
<item name="wcf.acp.group.option.mod.chat.canAlwaysEnter"><![CDATA[Kann Räume immer betreten]]></item>
|
||||||
<item name="wcf.acp.group.option.mod.chat.canAlwaysEnter.description"><![CDATA[Setzt Banns außer Kraft.]]></item>
|
<item name="wcf.acp.group.option.mod.chat.canAlwaysEnter.description"><![CDATA[Setzt Banns außer Kraft.]]></item>
|
||||||
<item name="wcf.acp.group.option.mod.chat.canAlwaysWrite"><![CDATA[Kann in jedem Raum schreiben]]></item>
|
<item name="wcf.acp.group.option.mod.chat.canAlwaysWrite"><![CDATA[Kann immer schreiben]]></item>
|
||||||
<item name="wcf.acp.group.option.mod.chat.canAlwaysWrite.description"><![CDATA[Setzt Knebel außer Kraft.]]></item>
|
<item name="wcf.acp.group.option.mod.chat.canAlwaysWrite.description"><![CDATA[Setzt Knebel außer Kraft.]]></item>
|
||||||
<item name="wcf.acp.group.option.mod.chat.canRestore"><![CDATA[Kann User zurücksetzen]]></item>
|
<item name="wcf.acp.group.option.mod.chat.canRestore"><![CDATA[Kann User zurücksetzen]]></item>
|
||||||
<item name="wcf.acp.group.option.mod.chat.canRestore.description"><![CDATA[Setzt Nutzerdaten (Farbe) zurück.]]></item>
|
<item name="wcf.acp.group.option.mod.chat.canRestore.description"><![CDATA[Setzt Nutzerdaten (Farbe) zurück.]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canBan"><![CDATA[Kann bannen]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canBan.description"><![CDATA[Impliziert „Kann Chat immer betreten“]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canMute"><![CDATA[Kann knebeln]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canMute.description"><![CDATA[Impliziert „Kann immer schreiben“]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canGban"><![CDATA[Kann global bannen]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canGban.description"><![CDATA[Impliziert „Kann bannen“]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canGmute"><![CDATA[Kann global knebeln]]></item>
|
||||||
|
<item name="wcf.acp.group.option.mod.chat.canGmute.description"><![CDATA[Impliziert „Kann knebeln“]]></item>
|
||||||
|
|
||||||
|
<item name="wcf.acp.group.option.category.admin.chat"><![CDATA[Chat]]></item>
|
||||||
|
<item name="wcf.acp.group.option.admin.chat.canManageSuspensions"><![CDATA[Kann Sanktionen verwalten]]></item>
|
||||||
|
<item name="wcf.acp.group.option.admin.chat.canManageSuspensions.description"><![CDATA[Impliziert „Kann bannen“, „Kann knebeln“, „Kann global bannen“, „Kann global knebeln“ und gegenbenenfalls weitere Rechte.]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="wcf.acp.option">
|
<category name="wcf.acp.option">
|
||||||
@ -59,7 +93,7 @@
|
|||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="chat.error">
|
<category name="chat.error">
|
||||||
<item name="chat.error.notFound"><![CDATA[Der Befehl wurde nicht gefunden.]]></item>
|
<item name="chat.error.notFound"><![CDATA[Der Befehl „{$exception->getCommand()}“ wurde nicht gefunden.]]></item>
|
||||||
<item name="chat.error.userNotFound"><![CDATA[Der Benutzer „{$exception->getUsername()}“ wurde nicht gefunden.]]></item>
|
<item name="chat.error.userNotFound"><![CDATA[Der Benutzer „{$exception->getUsername()}“ wurde nicht gefunden.]]></item>
|
||||||
<item name="chat.error.permissionDenied"><![CDATA[Sie dürfen diesen Befehl nicht verwenden.]]></item>
|
<item name="chat.error.permissionDenied"><![CDATA[Sie dürfen diesen Befehl nicht verwenden.]]></item>
|
||||||
<item name="chat.error.duplicateTab"><![CDATA[Der Chat wurde in einem weiteren Tab geöffnet.]]></item>
|
<item name="chat.error.duplicateTab"><![CDATA[Der Chat wurde in einem weiteren Tab geöffnet.]]></item>
|
||||||
@ -68,6 +102,9 @@
|
|||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="chat.general">
|
<category name="chat.general">
|
||||||
|
<item name="chat.general.expires"><![CDATA[Ablaufzeitpunkt]]></item>
|
||||||
|
<item name="chat.general.time"><![CDATA[Datum]]></item>
|
||||||
|
|
||||||
<item name="chat.general.title"><![CDATA[{lang}chat.header.menu.chat{/lang}]]></item>
|
<item name="chat.general.title"><![CDATA[{lang}chat.header.menu.chat{/lang}]]></item>
|
||||||
<item name="chat.general.protocol"><![CDATA[Protokoll]]></item>
|
<item name="chat.general.protocol"><![CDATA[Protokoll]]></item>
|
||||||
|
|
||||||
@ -100,6 +137,10 @@
|
|||||||
<item name="chat.general.information"><![CDATA[Information]]></item>
|
<item name="chat.general.information"><![CDATA[Information]]></item>
|
||||||
<item name="chat.general.information.chatUpdate"><![CDATA[Der Chat wurde aktualisiert. Bitte laden Sie die Seite neu, da es sonst zu Fehlern kommen kann.]]></item>
|
<item name="chat.general.information.chatUpdate"><![CDATA[Der Chat wurde aktualisiert. Bitte laden Sie die Seite neu, da es sonst zu Fehlern kommen kann.]]></item>
|
||||||
<item name="chat.general.information.suspension"><![CDATA[{lang}chat.suspension.{$suspension->type}{/lang} ({if $room}{$room}{else}{lang}chat.room.global{/lang}{/if})]]></item>
|
<item name="chat.general.information.suspension"><![CDATA[{lang}chat.suspension.{$suspension->type}{/lang} ({if $room}{$room}{else}{lang}chat.room.global{/lang}{/if})]]></item>
|
||||||
|
|
||||||
|
<item name="chat.general.privateChannelTopic"><![CDATA[{literal}Sie befinden sich in einem privaten Kanal mit „{$username}“, um diesen zu schließen, klicken Sie einfach auf das Kreuz rechts.{/literal}]]></item>
|
||||||
|
<item name="chat.general.closePrivateChannel"><![CDATA[Privaten Kanal schließen]]></item>
|
||||||
|
<item name="chat.general.closeTopic"><![CDATA[Thema ausblenden]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="chat.header">
|
<category name="chat.header">
|
||||||
@ -117,21 +158,21 @@
|
|||||||
<item name="chat.message.4"><![CDATA[ist jetzt wieder da.]]></item>
|
<item name="chat.message.4"><![CDATA[ist jetzt wieder da.]]></item>
|
||||||
<!-- 5 = TYPE_MODERATE -->
|
<!-- 5 = TYPE_MODERATE -->
|
||||||
<item name="chat.message.5.restore"><![CDATA[hat {@$link} zurückgesetzt.]]></item>
|
<item name="chat.message.5.restore"><![CDATA[hat {@$link} zurückgesetzt.]]></item>
|
||||||
<item name="chat.message.5.mute"><![CDATA[hat {@$link} bis {@$expires|plainTime} geknebelt.]]></item>
|
<item name="chat.message.5.mute"><![CDATA[hat {@$link} bis {@$expires|plainTime} geknebelt{if !$reason|empty}: {$reason}{else}.{/if}]]></item>
|
||||||
<item name="chat.message.5.ban"><![CDATA[hat {@$link} bis {@$expires|plainTime} gebannt.]]></item>
|
<item name="chat.message.5.ban"><![CDATA[hat {@$link} bis {@$expires|plainTime} gebannt{if !$reason|empty}: {$reason}{else}.{/if}]]></item>
|
||||||
<item name="chat.message.5.gmute"><![CDATA[hat {@$link} bis {@$expires|plainTime} global geknebelt.]]></item>
|
<item name="chat.message.5.gmute"><![CDATA[hat {@$link} bis {@$expires|plainTime} global geknebelt{if !$reason|empty}: {$reason}{else}.{/if}]]></item>
|
||||||
<item name="chat.message.5.gban"><![CDATA[hat {@$link} bis {@$expires|plainTime} global gebannt.]]></item>
|
<item name="chat.message.5.gban"><![CDATA[hat {@$link} bis {@$expires|plainTime} global gebannt{if !$reason|empty}: {$reason}{else}.{/if}]]></item>
|
||||||
<item name="chat.message.5.unmute"><![CDATA[hat {@$link} entknebelt.]]></item>
|
<item name="chat.message.5.unmute"><![CDATA[hat {@$link} entknebelt.]]></item>
|
||||||
<item name="chat.message.5.unban"><![CDATA[hat {@$link} entbannt.]]></item>
|
<item name="chat.message.5.unban"><![CDATA[hat {@$link} entbannt.]]></item>
|
||||||
<item name="chat.message.5.gunmute"><![CDATA[hat {@$link} global entknebelt.]]></item>
|
<item name="chat.message.5.ungmute"><![CDATA[hat {@$link} global entknebelt.]]></item>
|
||||||
<item name="chat.message.5.gunban"><![CDATA[hat {@$link} global entbannt.]]></item>
|
<item name="chat.message.5.ungban"><![CDATA[hat {@$link} global entbannt.]]></item>
|
||||||
|
|
||||||
<item name="chat.message.color.success"><![CDATA[Die Farbe wurde erfolgreich geändert.]]></item>
|
<item name="chat.message.color.success"><![CDATA[Die Farbe wurde erfolgreich geändert.]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="chat.suspension">
|
<category name="chat.suspension">
|
||||||
<item name="chat.suspension.1"><![CDATA[Knebel]]></item>
|
<item name="chat.suspension.mute"><![CDATA[Knebel]]></item>
|
||||||
<item name="chat.suspension.2"><![CDATA[Bann]]></item>
|
<item name="chat.suspension.ban"><![CDATA[Bann]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<!-- I18N Values -->
|
<!-- I18N Values -->
|
||||||
|
@ -49,7 +49,9 @@
|
|||||||
<optiontype>textarea</optiontype>
|
<optiontype>textarea</optiontype>
|
||||||
<defaultvalue>afk:away
|
<defaultvalue>afk:away
|
||||||
col:color
|
col:color
|
||||||
msg:whisper</defaultvalue>
|
msg:whisper
|
||||||
|
gunban:ungban
|
||||||
|
gunmute:ungmute</defaultvalue>
|
||||||
</option>
|
</option>
|
||||||
<!-- general chat options end -->
|
<!-- general chat options end -->
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<packagedescription><![CDATA[Chat for WoltLab Community Framework™.]]></packagedescription>
|
<packagedescription><![CDATA[Chat for WoltLab Community Framework™.]]></packagedescription>
|
||||||
<packagedescription language="de"><![CDATA[Chat für WoltLab Community Framework™.]]></packagedescription>
|
<packagedescription language="de"><![CDATA[Chat für WoltLab Community Framework™.]]></packagedescription>
|
||||||
<isapplication>1</isapplication>
|
<isapplication>1</isapplication>
|
||||||
<version>3.0.0 Alpha 58</version><!-- Codename: Codenames are overrated -->
|
<version>3.0.0 Alpha 80</version><!-- Codename: Codenames are overrated -->
|
||||||
<date>2011-11-26</date>
|
<date>2011-11-26</date>
|
||||||
<license><![CDATA[Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>]]></license>
|
<license><![CDATA[Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>]]></license>
|
||||||
</packageinformation>
|
</packageinformation>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{include file='headInclude' sandbox=false}
|
{include file='headInclude' sandbox=false}
|
||||||
{include file='javascriptInclude' application='chat'}
|
{include file='javascriptInclude' application='chat'}
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
(function ($, window) {
|
(function ($, window) {
|
||||||
$(function(){
|
$(function(){
|
||||||
@ -15,27 +15,33 @@
|
|||||||
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
||||||
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
||||||
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
||||||
|
'chat.general.privateChannelTopic': '{lang}chat.general.privateChannelTopic{/lang}',
|
||||||
|
'chat.general.closePrivateChannel': '{lang}chat.general.closePrivateChannel{/lang}',
|
||||||
|
'chat.general.closeTopic': '{lang}chat.general.closeTopic{/lang}',
|
||||||
'chat.error.onMessageLoad': '{lang}chat.error.onMessageLoad{/lang}',
|
'chat.error.onMessageLoad': '{lang}chat.error.onMessageLoad{/lang}',
|
||||||
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
||||||
'chat.error.join': '{lang}chat.error.join{/lang}',
|
'chat.error.join': '{lang}chat.error.join{/lang}',
|
||||||
'chat.error.reload': '{lang}chat.error.reload{/lang}'
|
'chat.error.reload': '{lang}chat.error.reload{/lang}'
|
||||||
});
|
});
|
||||||
|
|
||||||
{event name='beforeInit'}
|
|
||||||
|
|
||||||
// Boot the chat
|
// Boot the chat
|
||||||
{if MODULE_SMILEY}WCF.TabMenu.init();{/if}
|
{if MODULE_SMILEY}WCF.TabMenu.init();{/if}
|
||||||
new WCF.Message.Smilies();
|
new WCF.Message.Smilies();
|
||||||
{capture assign='messageTemplate'}{include application='chat' file='message'}{/capture}
|
{capture assign='messageTemplate'}{include application='chat' file='message'}{/capture}
|
||||||
{capture assign='userTemplate'}{include application='chat' file='userListUser'}{/capture}
|
{capture assign='userTemplate'}{include application='chat' file='userListUser'}{/capture}
|
||||||
|
|
||||||
be.bastelstu.Chat.init(
|
var config = {
|
||||||
{$roomID},
|
|
||||||
{
|
|
||||||
reloadTime: {@CHAT_RELOADTIME},
|
reloadTime: {@CHAT_RELOADTIME},
|
||||||
messageURL: '{link application="chat" controller="NewMessages"}{/link}',
|
messageURL: '{link application="chat" controller="NewMessages"}{/link}',
|
||||||
installedCommands: [ {implode from=$commands item='command'}'{$command|encodeJS}'{/implode} ]
|
installedCommands: [ {implode from=$commands item='command'}'{$command|encodeJS}'{/implode} ],
|
||||||
},
|
messageTypes: { {implode from=$messageTypes key='name' item='messageType'}'{$name|substr:5|encodeJS}': '{$messageType|encodeJS}'{/implode} }
|
||||||
|
};
|
||||||
|
|
||||||
|
{event name='beforeInit'}
|
||||||
|
|
||||||
|
be.bastelstu.Chat.init(
|
||||||
|
{$roomID},
|
||||||
|
config,
|
||||||
new WCF.Template('{literal}{if $newMessageCount}({#$newMessageCount}) {/if}{$title} - {/literal}{"chat.general.title"|language|encodeJS} - {PAGE_TITLE|language|encodeJS}'),
|
new WCF.Template('{literal}{if $newMessageCount}({#$newMessageCount}) {/if}{$title} - {/literal}{"chat.general.title"|language|encodeJS} - {PAGE_TITLE|language|encodeJS}'),
|
||||||
new WCF.Template('{@$messageTemplate|encodeJS}'),
|
new WCF.Template('{@$messageTemplate|encodeJS}'),
|
||||||
new WCF.Template('{@$userTemplate|encodeJS}')
|
new WCF.Template('{@$userTemplate|encodeJS}')
|
||||||
@ -54,36 +60,31 @@
|
|||||||
})(jQuery, this);
|
})(jQuery, this);
|
||||||
//]]>
|
//]]>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
.timsChatMessage::before {
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
{assign var='type' value='\chat\data\message\Message::TYPE_'}
|
|
||||||
.timsChatMessage{$type|concat:'JOIN'|constant}::before {
|
|
||||||
content: "\f090";
|
|
||||||
}
|
|
||||||
|
|
||||||
.timsChatMessage{$type|concat:'LEAVE'|constant}::before {
|
|
||||||
content: "\f08b";
|
|
||||||
}
|
|
||||||
|
|
||||||
.timsChatMessage{$type|concat:'INFORMATION'|constant}::before {
|
|
||||||
content: "\f05a";
|
|
||||||
}
|
|
||||||
/*]]>*/
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="tpl{$templateName|ucfirst}">
|
<body id="tpl{$templateName|ucfirst}">
|
||||||
{capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture}
|
{capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture}
|
||||||
{include file='header' sandbox=false sidebarOrientation='right'}
|
{include file='header' sandbox=false sidebarOrientation='right'}
|
||||||
|
|
||||||
<div id="timsChatTopic" class="container{if $room->topic|language === ''} empty{/if}">{$room->topic|language}</div>
|
<div id="timsChatTopic" class="container{if $room->topic|language === ''} empty{/if}">
|
||||||
|
<span class="icon icon16 icon-remove jsTopicCloser jsTooltip" title="{lang}chat.general.closeTopic{/lang}"></span>
|
||||||
|
<span class="topic">{$room->topic|language}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="timsChatMessageContainer" class="timsChatMessageContainer marginTop container active">
|
<div id="privateChannelsMenu">
|
||||||
|
<ul>
|
||||||
|
<li id="privateChannel0" class="privateChannel active" data-private-channel-id="0">
|
||||||
|
<span class="userAvatar framed small">
|
||||||
|
<span class="icon icon16 icon-comment-alt jsTooltip" title="{lang}chat.general.room{/lang}"></span>
|
||||||
|
</span>
|
||||||
|
<span class="userAvatar framed large">
|
||||||
|
<span class="icon icon32 icon-comment-alt jsTooltip" title="{lang}chat.general.room{/lang}"></span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="timsChatMessageContainer0" class="timsChatMessageContainer marginTop container active" data-user-id="0">
|
||||||
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
||||||
<ul>
|
<ul>
|
||||||
</ul>
|
</ul>
|
||||||
@ -93,7 +94,7 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<dl class="wide" id="timsChatInputContainer">
|
<dl class="wide" id="timsChatInputContainer">
|
||||||
<dd>
|
<dd>
|
||||||
<input id="timsChatInput" accesskey="w" type="text" class="inputText long" name="text" autocomplete="off" maxlength="{@CHAT_MAX_LENGTH}" disabled="disabled" required="required" placeholder="{lang}chat.general.submit.default{/lang}" />
|
<input id="timsChatInput" accesskey="w" type="text" class="inputText long" name="text" autocomplete="off" maxlength="{@CHAT_MAX_LENGTH}" disabled="disabled" placeholder="{lang}chat.general.submit.default{/lang}" />
|
||||||
<small class="innerError" style="display: none;">Lorem ipsum dolor sit amet.</small>
|
<small class="innerError" style="display: none;">Lorem ipsum dolor sit amet.</small>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@ -105,7 +106,7 @@
|
|||||||
{include file='messageFormSmilies' wysiwygSelector=''}
|
{include file='messageFormSmilies' wysiwygSelector=''}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<nav id="timsChatOptions" class="marginTop buttonGroupNavigation">
|
<nav id="timsChatOptions" class="marginTop jsMobileNavigation buttonGroupNavigation">
|
||||||
<span class="invisible">{lang}chat.general.controls{/lang}</span>
|
<span class="invisible">{lang}chat.general.controls{/lang}</span>
|
||||||
<ul class="smallButtons buttonGroup">
|
<ul class="smallButtons buttonGroup">
|
||||||
<li><a id="timsChatAutoscroll" accesskey="d" class="button active timsChatToggle jsTooltip" title="{lang}chat.general.scroll{/lang}" data-status="1"><span class="icon icon16 icon-arrow-down"></span><span class="invisible">{lang}chat.general.scroll{/lang}</span></a></li>{*
|
<li><a id="timsChatAutoscroll" accesskey="d" class="button active timsChatToggle jsTooltip" title="{lang}chat.general.scroll{/lang}" data-status="1"><span class="icon icon16 icon-arrow-down"></span><span class="invisible">{lang}chat.general.scroll{/lang}</span></a></li>{*
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
{@$roomList}
|
{@$roomList}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
(function($, window, undefined) {
|
(function($, window, undefined) {
|
||||||
proxy = new WCF.Action.Proxy({
|
proxy = new WCF.Action.Proxy({
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<script type="text/javascript" src="{$__wcf->getPath('chat')}js/be.bastelstu.Chat{if !ENABLE_DEBUG_MODE}.min{/if}.js?version={PACKAGE_VERSION|rawurlencode}"></script>
|
<script src="{$__wcf->getPath('chat')}js/be.bastelstu.Chat{if !ENABLE_DEBUG_MODE}.min{/if}.js?version={PACKAGE_VERSION|rawurlencode}"></script>
|
||||||
<!--script type="text/javascript" src="{$__wcf->getPath('chat')}js/be.bastelstu.Chat.Log{if !ENABLE_DEBUG_MODE}.min{/if}.js?version={PACKAGE_VERSION|rawurlencode}"></script-->
|
<!--script src="{$__wcf->getPath('chat')}js/be.bastelstu.Chat.Log{if !ENABLE_DEBUG_MODE}.min{/if}.js?version={PACKAGE_VERSION|rawurlencode}"></script-->
|
||||||
{event name='javascript'}
|
{event name='javascript'}
|
@ -4,7 +4,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
var log = new be.bastelstu.Chat.Log(chat);
|
var log = new be.bastelstu.Chat.Log(chat);
|
||||||
log.handleMessages([
|
log.handleMessages([
|
||||||
|
@ -1,24 +1,54 @@
|
|||||||
{literal}
|
{literal}
|
||||||
<time>{@$formattedTime}</time>
|
<div class="messageIcon">
|
||||||
<span class="usernameContainer">
|
{if $message.type == $messageTypes.LEAVE || $message.type == $messageTypes.JOIN}
|
||||||
<span class="username">{*
|
<span class="icon icon16 icon-{if $message.type == $messageTypes.LEAVE}signout{else}signin{/if}"></span>
|
||||||
*}{if $type != 7}{*
|
{/if}
|
||||||
*}{@$formattedUsername}{*
|
</div>
|
||||||
*}{else}
|
<div class="innerMessageContainer{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.INFORMATION} bubble{/if}{if $message.type == $messageTypes.WHISPER && $message.sender != $__wcf.User.userID} right{/if}">
|
||||||
{if $receiver == WCF.User.userID}
|
<div class="userAvatar framed">
|
||||||
{@$formattedUsername}
|
{if $message.type != $messageTypes.INFORMATION}
|
||||||
|
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER}
|
||||||
|
{@$message.avatar[32]}
|
||||||
|
{else}
|
||||||
|
{@$message.avatar[16]}
|
||||||
|
{/if}
|
||||||
|
{else}
|
||||||
|
<span class="icon icon32 icon-info-sign"></span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="innerMessage">
|
||||||
|
<span class="username">
|
||||||
|
{if ($message.type == $messageTypes.WHISPER && $message.sender == WCF.User.userID) || $message.type != $messageTypes.WHISPER}
|
||||||
|
{@$message.formattedUsername}
|
||||||
|
{else}
|
||||||
|
{$message.additionalData.receiverUsername}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{if $message.type == $messageTypes.WHISPER}
|
||||||
|
<span class="icon icon16 icon-double-angle-{if $message.sender == WCF.User.userID}right{else}left{/if} jsTooltip" title="{/literal}{lang}chat.ui.whispers{/lang}{literal}" onclick="be.bastelstu.Chat.insertText('/whisper {if $message.receiver == WCF.User.userID}{$message.username.replace("\\", "\\\\").replace("'", "\\'")}{else}{$message.additionalData.receiverUsername.replace("\\", "\\\\").replace("'", "\\'")}{/if}, ', { append: false });"></span>
|
||||||
|
{if ($message.type == $messageTypes.WHISPER && $message.sender == WCF.User.userID) || $message.type != $messageTypes.WHISPER}
|
||||||
|
{$message.additionalData.receiverUsername}
|
||||||
|
{else}
|
||||||
|
{@$message.formattedUsername}
|
||||||
{/if}
|
{/if}
|
||||||
<span class="icon icon16 icon-double-angle-right jsTooltip" title="{/literal}{lang}chat.ui.whispers{/lang}{literal}" onclick="be.bastelstu.Chat.insertText('/whisper {if $receiver == WCF.User.userID}{$username.replace("\\", "\\\\").replace("'", "\\'")}{else}{$additionalData.receiverUsername.replace("\\", "\\\\").replace("'", "\\'")}{/if}, ', { append: false });"></span>
|
|
||||||
{if $receiver != WCF.User.userID}
|
|
||||||
{$additionalData.receiverUsername}{/if}{*
|
|
||||||
*}{/if}{*
|
|
||||||
*}</span>{*
|
|
||||||
*}{if $receiver != WCF.User.userID}{*
|
|
||||||
*}<span class="separator">{$separator}</span>
|
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<span class="text">{@$formattedMessage}</span>
|
|
||||||
|
<time>{@$message.formattedTime}</time>
|
||||||
|
|
||||||
|
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER}
|
||||||
|
<ul class="text">
|
||||||
|
<li>
|
||||||
|
{if $message.isFollowUp} <time>{@$message.formattedTime}</time>{/if}
|
||||||
|
{@$message.formattedMessage}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{else}
|
||||||
|
<span class="text">{@$message.formattedMessage}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
<span class="markContainer">
|
<span class="markContainer">
|
||||||
<input type="checkbox" value="{@$messageID}" />
|
<input type="checkbox" value="{@$message.messageID}" />
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
{/literal}
|
{/literal}
|
||||||
|
@ -104,6 +104,12 @@
|
|||||||
<defaultvalue>0</defaultvalue>
|
<defaultvalue>0</defaultvalue>
|
||||||
<admindefaultvalue>1</admindefaultvalue>
|
<admindefaultvalue>1</admindefaultvalue>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="admin.chat.canManageSuspensions">
|
||||||
|
<categoryname>admin.chat</categoryname>
|
||||||
|
<optiontype>boolean</optiontype>
|
||||||
|
<defaultvalue>0</defaultvalue>
|
||||||
|
<admindefaultvalue>1</admindefaultvalue>
|
||||||
|
</option>
|
||||||
</options>
|
</options>
|
||||||
</import>
|
</import>
|
||||||
</data>
|
</data>
|
Loading…
Reference in New Issue
Block a user