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
|
||||
php:
|
||||
- 5.5
|
||||
- 5.4
|
||||
- 5.3
|
||||
before_install:
|
||||
|
@ -23,6 +23,13 @@
|
||||
<showorder>2</showorder>
|
||||
</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">
|
||||
<controller><![CDATA[chat\acp\page\MessageLogListPage]]></controller>
|
||||
<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}
|
||||
|
||||
<script type="text/javascript" src="{@$__wcf->getPath('wcf')}js/WCF.ACL.js"></script>
|
||||
<script type="text/javascript">
|
||||
<script src="{@$__wcf->getPath('wcf')}js/WCF.ACL.js"></script>
|
||||
<script>
|
||||
//<![CDATA[
|
||||
$(function() {
|
||||
new WCF.ACL.List($('#groupPermissions'), {@$objectTypeID}, ''{if $roomID|isset}, {@$roomID}{/if});
|
||||
|
@ -1,6 +1,6 @@
|
||||
{include file='header' pageTitle='chat.acp.room.list'}
|
||||
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
//<![CDATA[
|
||||
$(function() {
|
||||
new WCF.Action.Delete('\\chat\\data\\room\\RoomAction', $('.chatRoomRow'));
|
||||
|
@ -33,7 +33,16 @@ exposed by a function if necessary.
|
||||
newMessageCount = 0
|
||||
scrollUpNotifications = off
|
||||
chatSession = Date.now()
|
||||
userList =
|
||||
current: {}
|
||||
allTime: {}
|
||||
currentRoom = {}
|
||||
|
||||
errorVisible = false
|
||||
inputErrorHidingTimer = null
|
||||
|
||||
lastMessage = null
|
||||
openChannel = 0
|
||||
|
||||
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.
|
||||
|
||||
$('#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
|
||||
and afterwards sent to the server by an AJAX request.
|
||||
|
||||
$('#timsChatForm').submit (event) ->
|
||||
event.preventDefault()
|
||||
do event.preventDefault
|
||||
|
||||
text = $('#timsChatInput').val().trim()
|
||||
text = do $('#timsChatInput').val().trim
|
||||
$('#timsChatInput').val('').focus().keyup()
|
||||
|
||||
return false if text.length is 0
|
||||
|
||||
unless openChannel is 0
|
||||
text = "/whisper #{userList.allTime[openChannel].username}, #{text}"
|
||||
|
||||
# Free the fish!
|
||||
freeTheFish() if text.toLowerCase() is '/free the fish'
|
||||
do freeTheFish if text.toLowerCase() is '/free the fish'
|
||||
|
||||
text = do (text) ->
|
||||
obj =
|
||||
@ -139,16 +156,13 @@ and afterwards sent to the server by an AJAX request.
|
||||
enableSmilies: $('#timsChatSmilies').data 'status'
|
||||
showLoadingOverlay: false
|
||||
success: ->
|
||||
$('#timsChatInputContainer').removeClass('formError').find('.innerError').hide()
|
||||
getMessages()
|
||||
do hideInputError
|
||||
|
||||
do getMessages
|
||||
failure: (data) ->
|
||||
return true unless (data?.returnValues?.errorType?) or (data?.message?)
|
||||
|
||||
$('#timsChatInputContainer').addClass('formError').find('.innerError').show().html (data?.returnValues?.errorType) ? data.message
|
||||
|
||||
setTimeout ->
|
||||
$('#timsChatInputContainer').removeClass('formError').find('.innerError').hide()
|
||||
, 5e3
|
||||
showInputError (data?.returnValues?.errorType) ? data.message
|
||||
|
||||
false
|
||||
|
||||
@ -157,11 +171,11 @@ The the word the caret is in will be passed to `autocomplete` and replaced if a
|
||||
|
||||
$('#timsChatInput').keydown (event) ->
|
||||
if event.keyCode is $.ui.keyCode.TAB
|
||||
input = $(event.currentTarget)
|
||||
event.preventDefault()
|
||||
do event.preventDefault
|
||||
input = $ @
|
||||
|
||||
autocomplete.value ?= input.val()
|
||||
autocomplete.caret ?= input.getCaret()
|
||||
autocomplete.value ?= do input.val
|
||||
autocomplete.caret ?= do input.getCaret
|
||||
|
||||
beforeCaret = autocomplete.value.substring 0, autocomplete.caret
|
||||
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
|
||||
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"
|
||||
# TODO: Proper command list
|
||||
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
|
||||
else
|
||||
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
|
||||
|
||||
@ -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.
|
||||
|
||||
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.
|
||||
|
||||
@ -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.
|
||||
|
||||
$('#timsChatRoomList button').click ->
|
||||
refreshRoomList()
|
||||
do refreshRoomList
|
||||
|
||||
Clear the chat by removing every single message once the clear button is `clicked`.
|
||||
|
||||
$('#timsChatClear').click (event) ->
|
||||
event.preventDefault()
|
||||
$('.timsChatMessage').remove()
|
||||
$('#timsChatMessageContainer').scrollTop $('#timsChatMessageContainer').prop('scrollHeight')
|
||||
do event.preventDefault
|
||||
do $('.timsChatMessageContainer.active .timsChatMessage').remove
|
||||
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop 'scrollHeight'
|
||||
|
||||
Handle toggling of the toggleable buttons.
|
||||
|
||||
@ -230,7 +247,7 @@ Handle toggling of the toggleable buttons.
|
||||
element.addClass 'active'
|
||||
element.attr 'title', element.data 'disableMessage'
|
||||
|
||||
$('#timsChatInput').focus()
|
||||
do $('#timsChatInput').focus
|
||||
|
||||
Mark smilies as disabled when they are disabled.
|
||||
|
||||
@ -251,7 +268,7 @@ Toggle fullscreen mode.
|
||||
else
|
||||
$('html').removeClass 'fullscreen'
|
||||
|
||||
Toggle checkboxes
|
||||
Toggle checkboxes.
|
||||
|
||||
$('#timsChatMark').click (event) ->
|
||||
if $(@).data 'status'
|
||||
@ -259,6 +276,14 @@ Toggle checkboxes
|
||||
else
|
||||
$('.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.
|
||||
|
||||
$(document).on 'click', '.timsChatMessage :checkbox', (event) ->
|
||||
@ -271,9 +296,9 @@ Scroll down when autoscroll is being activated.
|
||||
|
||||
$('#timsChatAutoscroll').click (event) ->
|
||||
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 = $ @
|
||||
scrollTop = element.scrollTop()
|
||||
scrollHeight = element.prop 'scrollHeight'
|
||||
@ -282,13 +307,13 @@ Scroll down when autoscroll is being activated.
|
||||
if scrollTop < scrollHeight - height - 25
|
||||
if $('#timsChatAutoscroll').data('status') is 1
|
||||
scrollUpNotifications = on
|
||||
$('#timsChatAutoscroll').click()
|
||||
do $('#timsChatAutoscroll').click
|
||||
|
||||
if scrollTop > scrollHeight - height - 10
|
||||
if $('#timsChatAutoscroll').data('status') is 0
|
||||
scrollUpNotifications = off
|
||||
$(@).removeClass 'notification'
|
||||
$('#timsChatAutoscroll').click()
|
||||
do $('#timsChatAutoscroll').click
|
||||
|
||||
Enable duplicate tab detection.
|
||||
|
||||
@ -321,11 +346,11 @@ load messages if the appropriate event arrives.
|
||||
do ->
|
||||
be.bastelstu.wcf.nodePush.onConnect ->
|
||||
console.log 'Disabling periodic loading'
|
||||
pe.getMessages.stop()
|
||||
do pe.getMessages.stop
|
||||
|
||||
be.bastelstu.wcf.nodePush.onDisconnect ->
|
||||
console.log 'Enabling periodic loading'
|
||||
getMessages()
|
||||
do getMessages
|
||||
pe.getMessages = new WCF.PeriodicalExecuter getMessages, v.config.reloadTime * 1e3
|
||||
|
||||
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.
|
||||
|
||||
join roomID
|
||||
$('#timsChatInput').enable().jCounter().focus();
|
||||
do $('#timsChatInput').enable().jCounter().focus
|
||||
|
||||
console.log "Finished initializing"
|
||||
|
||||
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.
|
||||
|
||||
freeTheFish = ->
|
||||
return if $.wcfIsset 'fish'
|
||||
console.warn 'Freeing the fish'
|
||||
fish = $ """<div id="fish">#{WCF.String.escapeHTML('><((((\u00B0>')}</div>"""
|
||||
|
||||
fish.css
|
||||
position: 'absolute'
|
||||
top: '150px'
|
||||
@ -389,7 +433,7 @@ Fetch new messages from the server and pass them to `handleMessages`. The userli
|
||||
error: ->
|
||||
console.error "Message loading failed, #{--remainingFailures} remaining"
|
||||
if remainingFailures <= 0
|
||||
freeTheFish()
|
||||
do freeTheFish
|
||||
console.error 'To many failures, aborting'
|
||||
|
||||
showError WCF.Language.get 'chat.error.onMessageLoad'
|
||||
@ -406,12 +450,24 @@ Prevent loading messages in parallel.
|
||||
Insert the given messages into the chat stream.
|
||||
|
||||
handleMessages = (messages) ->
|
||||
$('#timsChatMessageContainer').trigger 'scroll'
|
||||
$('.timsChatMessageContainer.active').trigger 'scroll'
|
||||
|
||||
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
|
||||
|
||||
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.addClass 'timsChatMessage'
|
||||
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.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`.
|
||||
|
||||
handleUsers = (users) ->
|
||||
foundUsers = { }
|
||||
userList.current = { }
|
||||
|
||||
for user in users
|
||||
do (user) ->
|
||||
userList.current[user.userID] = userList.allTime[user.userID] = user
|
||||
|
||||
id = "timsChatUser#{user.userID}"
|
||||
|
||||
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
|
||||
|
||||
menu = $ '<ul></ul>'
|
||||
menu.addClass 'dropdownMenu'
|
||||
menu.append $ "<li><a>#{WCF.Language.get('chat.general.query')}</a></li>"
|
||||
unless user.userID is WCF.User.userID
|
||||
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.ban')}</a></li>"
|
||||
menu.append $ """<li><a href="#{user.link}">#{WCF.Language.get('chat.general.profile')}</a></li>"""
|
||||
|
||||
events.userMenu.fire user, menu
|
||||
|
||||
if menu.find('li').length
|
||||
li.append menu
|
||||
menu.addClass 'dropdownMenu'
|
||||
|
||||
li.appendTo $ '#timsChatUserList > ul'
|
||||
|
||||
foundUsers[id] = true
|
||||
@ -489,7 +572,7 @@ Remove all users that left the chat.
|
||||
$('.timsChatUser').each ->
|
||||
unless foundUsers[$(@).attr('id')]?
|
||||
console.log "Removing User: '#{$(@).data('username')}'"
|
||||
$(@).remove();
|
||||
do $(@).remove
|
||||
|
||||
|
||||
$('#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
|
||||
$('#timsChatInput').val text
|
||||
$('#timsChatInput').keyup()
|
||||
do $('#timsChatInput').keyup
|
||||
|
||||
if (options.submit)
|
||||
$('#timsChatForm').submit()
|
||||
if options.submit
|
||||
do $('#timsChatForm').submit
|
||||
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.
|
||||
|
||||
notify = (message) ->
|
||||
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
|
||||
|
||||
@ -532,9 +626,9 @@ Send out notifications for the given `message`. The number of unread messages wi
|
||||
notification = new window.Notification title,
|
||||
body: content
|
||||
onclick: ->
|
||||
notification.close()
|
||||
do notification.close
|
||||
setTimeout ->
|
||||
notification.close()
|
||||
do notification.close
|
||||
, 5e3
|
||||
|
||||
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
|
||||
suppressErrors: true
|
||||
success: (data) ->
|
||||
$('.timsChatRoom').remove()
|
||||
do $('.timsChatRoom').remove
|
||||
$('#toggleRooms .badge').text data.returnValues.length
|
||||
|
||||
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?
|
||||
$('.timsChatRoom').click (event) ->
|
||||
event.preventDefault()
|
||||
target = $(@)
|
||||
do event.preventDefault
|
||||
target = $ @
|
||||
|
||||
window.history.replaceState {}, '', target.attr 'href'
|
||||
|
||||
@ -580,8 +674,8 @@ Shows an unrecoverable error with the given text.
|
||||
|
||||
loading = true
|
||||
|
||||
pe.refreshRoomList.stop()
|
||||
pe.getMessages.stop()
|
||||
do pe.refreshRoomList.stop
|
||||
do pe.getMessages.stop
|
||||
|
||||
errorDialog = $("""
|
||||
<div id="timsChatLoadingErrorDialog">
|
||||
@ -592,7 +686,7 @@ Shows an unrecoverable error with the given text.
|
||||
formSubmit = $("""<div class="formSubmit"></div>""").appendTo errorDialog
|
||||
reloadButton = $("""<button class="buttonPrimary">#{WCF.Language.get 'chat.error.reload'}</button>""").appendTo formSubmit
|
||||
reloadButton.on 'click', ->
|
||||
window.location.reload()
|
||||
do window.location.reload
|
||||
|
||||
$('#timsChatLoadingErrorDialog').wcfDialog
|
||||
closable: false
|
||||
@ -612,35 +706,116 @@ Joins a room.
|
||||
success: (data) ->
|
||||
loading = false
|
||||
|
||||
$('#timsChatTopic').text data.returnValues.topic
|
||||
if data.returnValues.topic.trim() is ''
|
||||
$('#timsChatTopic').removeClass 'hidden'
|
||||
currentRoom = data.returnValues
|
||||
currentRoom.roomID = roomID
|
||||
|
||||
$('#timsChatTopic > .topic').text currentRoom.topic
|
||||
if currentRoom.topic.trim() is ''
|
||||
$('#timsChatTopic').addClass 'empty'
|
||||
else
|
||||
$('#timsChatTopic').removeClass 'empty'
|
||||
|
||||
$('.timsChatMessage').addClass 'unloaded'
|
||||
|
||||
document.title = v.titleTemplate.fetch data.returnValues
|
||||
handleMessages data.returnValues.messages
|
||||
getMessages()
|
||||
refreshRoomList()
|
||||
document.title = v.titleTemplate.fetch currentRoom
|
||||
handleMessages currentRoom.messages
|
||||
do getMessages
|
||||
do refreshRoomList
|
||||
failure: ->
|
||||
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.
|
||||
|
||||
addListener = (event, callback) ->
|
||||
return false unless events[event]?
|
||||
|
||||
events[event].add callback
|
||||
|
||||
true
|
||||
|
||||
Remove the given callback from the given event.
|
||||
|
||||
removeListener = (event, callback) ->
|
||||
return false unless events[event]?
|
||||
|
||||
events[event].remove callback
|
||||
|
||||
true
|
||||
|
||||
And finally export the public methods and variables.
|
||||
|
||||
Chat =
|
||||
@ -650,6 +825,8 @@ And finally export the public methods and variables.
|
||||
insertText: insertText
|
||||
freeTheFish: freeTheFish
|
||||
join: join
|
||||
closePrivateChannel: closePrivateChannel # TODO: REMOVE AFTER DEBUGGING
|
||||
openPrivateChannel: openPrivateChannel # TODO: REMOVE AFTER DEBUGGING
|
||||
listener:
|
||||
add: addListener
|
||||
remove: removeListener
|
||||
|
@ -116,7 +116,7 @@ public function save() {
|
||||
}
|
||||
|
||||
\wcf\system\acl\ACLHandler::getInstance()->save($roomID, $this->objectTypeID);
|
||||
\chat\system\permission\permissionHandler::clearCache();
|
||||
\chat\system\permission\PermissionHandler::clearCache();
|
||||
|
||||
$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>
|
||||
*/
|
||||
public static function getNewestMessages(\chat\data\room\Room $room, $number = CHAT_LASTMESSAGES) {
|
||||
if ($number === 0) return array();
|
||||
|
||||
$messageList = new static();
|
||||
$messageList->sqlOrderBy = "message.messageID DESC";
|
||||
$messageList->sqlLimit = $number;
|
||||
|
@ -39,26 +39,33 @@ public function __toString() {
|
||||
public function canEnter(\wcf\data\user\User $user = null) {
|
||||
if ($user === null) $user = WCF::getUser();
|
||||
if (!$user->userID) return false;
|
||||
$user = new \wcf\data\user\UserProfile($user);
|
||||
|
||||
$ph = new \chat\system\permission\PermissionHandler($user);
|
||||
$suspensions = Suspension::getSuspensionsForUser($user);
|
||||
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||
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
|
||||
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()) {
|
||||
$canEnter = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// global suspension
|
||||
if ($canEnter && isset($suspensions[null][Suspension::TYPE_BAN])) {
|
||||
if (isset($suspensions[null][Suspension::TYPE_BAN])) {
|
||||
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) {
|
||||
if ($user === null) $user = WCF::getUser();
|
||||
if (!$user->userID) return false;
|
||||
$user = new \wcf\data\user\UserProfile($user);
|
||||
|
||||
$ph = new \chat\system\permission\PermissionHandler($user);
|
||||
$suspensions = Suspension::getSuspensionsForUser($user);
|
||||
if ($user->getPermission('admin.chat.canManageSuspensions')) return true;
|
||||
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
|
||||
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()) {
|
||||
$canWrite = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// global suspension
|
||||
if ($canWrite && isset($suspensions[null][Suspension::TYPE_MUTE])) {
|
||||
if (isset($suspensions[null][Suspension::TYPE_MUTE])) {
|
||||
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();
|
||||
}
|
||||
|
||||
$newestMessages = message\ViewableMessageList::getNewestMessages($room, CHAT_LASTMESSAGES);
|
||||
$newestMessages = message\ViewableMessageList::getNewestMessages($room, CHAT_LASTMESSAGES + CHAT_DISPLAY_JOIN_LEAVE);
|
||||
|
||||
try {
|
||||
$lastSeen = end($newestMessages)->messageID;
|
||||
}
|
||||
catch (\wcf\system\exception\SystemException $e) {
|
||||
$lastSeen = 0;
|
||||
}
|
||||
// update last seen message
|
||||
$sql = "SELECT
|
||||
MAX(messageID)
|
||||
FROM
|
||||
chat".WCF_N."_message";
|
||||
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||
$stmt->execute();
|
||||
|
||||
$editor = new \wcf\data\user\UserEditor($this->parameters['user']);
|
||||
$editor->update(array(
|
||||
'chatRoomID' => $room->roomID,
|
||||
'chatAway' => null,
|
||||
'chatLastActivity' => TIME_NOW,
|
||||
'chatLastSeen' => $lastSeen
|
||||
'chatLastSeen' => $stmt->fetchColumn() ?: 0
|
||||
));
|
||||
|
||||
// add activity points
|
||||
|
@ -22,8 +22,8 @@ class Suspension extends \chat\data\CHATDatabaseObject {
|
||||
*/
|
||||
protected static $databaseTableIndexName = 'suspensionID';
|
||||
|
||||
const TYPE_MUTE = 1;
|
||||
const TYPE_BAN = 2;
|
||||
const TYPE_MUTE = 'mute';
|
||||
const TYPE_BAN = 'ban';
|
||||
|
||||
/**
|
||||
* Returns whether the suspension still is valid.
|
||||
@ -34,6 +34,36 @@ public function isValid() {
|
||||
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).
|
||||
*
|
||||
@ -53,15 +83,17 @@ public static function getSuspensionsForUser(\wcf\data\user\User $user = null) {
|
||||
if ($suspensions === false) throw new \wcf\system\exception\SystemException();
|
||||
}
|
||||
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
|
||||
*
|
||||
FROM
|
||||
chat".WCF_N."_suspension
|
||||
WHERE
|
||||
userID = ?
|
||||
AND expires > ?";
|
||||
".$condition;
|
||||
$stmt = WCF::getDB()->prepareStatement($sql);
|
||||
$stmt->execute(array($user->userID, TIME_NOW));
|
||||
$stmt->execute($condition->getParameters());
|
||||
|
||||
$suspensions = array();
|
||||
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 false if no suspension was found.
|
||||
* Returns false if no active suspension was found.
|
||||
*
|
||||
* @param \wcf\data\user\User $user
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
*
|
||||
FROM
|
||||
chat".WCF_N."_suspension
|
||||
WHERE
|
||||
userID = ?
|
||||
AND type = ?";
|
||||
|
||||
$parameter = array($user->userID, $type);
|
||||
if ($room->roomID) {
|
||||
$sql .= " AND roomID = ?";
|
||||
$parameter[] = $room->roomID;
|
||||
}
|
||||
else $sql .= " AND roomID IS NULL";
|
||||
".$condition;
|
||||
|
||||
$statement = WCF::getDB()->prepareStatement($sql);
|
||||
$statement->execute($parameter);
|
||||
$statement->execute($condition->getParameters());
|
||||
$row = $statement->fetchArray();
|
||||
if (!$row) return false;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace chat\data\suspension;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Executes chat-suspension-related actions.
|
||||
@ -17,23 +18,28 @@ class SuspensionAction extends \wcf\data\AbstractDatabaseObjectAction {
|
||||
protected $className = '\chat\data\suspension\SuspensionEditor';
|
||||
|
||||
/**
|
||||
* Deletes expired suspensions.
|
||||
*
|
||||
* @return integer Number of deleted suspensions
|
||||
* Validates permissions and parameters
|
||||
*/
|
||||
public function prune() {
|
||||
$sql = "SELECT
|
||||
".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();
|
||||
public function validateRevoke() {
|
||||
WCF::getSession()->checkPermissions((array) 'admin.chat.canManageSuspensions');
|
||||
|
||||
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() {
|
||||
parent::assignVariables();
|
||||
|
||||
$reflection = new \ReflectionClass('\chat\data\message\Message');
|
||||
|
||||
WCF::getTPL()->assign(array(
|
||||
'room' => $this->room,
|
||||
'roomID' => $this->roomID,
|
||||
'rooms' => $this->rooms,
|
||||
'commands' => $this->commands,
|
||||
'messageTypes' => $reflection->getConstants(),
|
||||
'defaultSmilies' => $this->defaultSmilies,
|
||||
'smileyCategories' => $this->smileyCategories,
|
||||
'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();
|
||||
|
||||
@header('Content-type: application/json');
|
||||
// enable gzip compression
|
||||
if (HTTP_ENABLE_GZIP && HTTP_GZIP_LEVEL > 0 && HTTP_GZIP_LEVEL < 10 && !defined('HTTP_DISABLE_GZIP')) {
|
||||
\wcf\util\HeaderUtil::compressOutput();
|
||||
}
|
||||
\wcf\util\HeaderUtil::sendNoCacheHeaders();
|
||||
|
||||
$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() {
|
||||
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
|
||||
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.
|
||||
@ -14,25 +10,7 @@
|
||||
* @package be.bastelstu.chat
|
||||
* @subpackage system.chat.command.commands
|
||||
*/
|
||||
class BanCommand extends MuteCommand {
|
||||
public function executeAction() {
|
||||
if ($suspension = suspension\Suspension::getSuspensionByUserRoomAndType($this->user, $this->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' => WCF::getUser()->chatRoomID,
|
||||
'type' => suspension\Suspension::TYPE_BAN,
|
||||
'expires' => $this->expires
|
||||
)
|
||||
));
|
||||
$this->suspensionAction->executeAction();
|
||||
}
|
||||
class BanCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||
const IS_GLOBAL = false;
|
||||
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
<?php
|
||||
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.
|
||||
@ -14,27 +10,7 @@
|
||||
* @package be.bastelstu.chat
|
||||
* @subpackage system.chat.command.commands
|
||||
*/
|
||||
class GbanCommand extends MuteCommand {
|
||||
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)) {
|
||||
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();
|
||||
}
|
||||
class GbanCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||
const IS_GLOBAL = true;
|
||||
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
<?php
|
||||
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
|
||||
* @copyright 2010-2013 Tim Düsterhus
|
||||
@ -14,27 +10,7 @@
|
||||
* @package be.bastelstu.chat
|
||||
* @subpackage system.chat.command.commands
|
||||
*/
|
||||
class GmuteCommand extends MuteCommand {
|
||||
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)) {
|
||||
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();
|
||||
}
|
||||
class GmuteCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||
const IS_GLOBAL = true;
|
||||
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||
}
|
||||
|
@ -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
|
||||
// TODO: Permissions
|
||||
$suspensions = \chat\data\suspension\Suspension::getSuspensionsForUser($this->user);
|
||||
foreach ($suspensions as $roomSuspensions) {
|
||||
foreach ($roomSuspensions as $typeSuspension) {
|
||||
if (!$typeSuspension->isValid()) continue;
|
||||
if (!$typeSuspension->isVisible()) continue;
|
||||
|
||||
$dateTime = DateUtil::getDateTimeByTimestamp($typeSuspension->expires);
|
||||
$name = WCF::getLanguage()->getDynamicVariable('chat.general.information.suspension', array(
|
||||
|
@ -1,9 +1,5 @@
|
||||
<?php
|
||||
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.
|
||||
@ -14,86 +10,7 @@
|
||||
* @package be.bastelstu.chat
|
||||
* @subpackage system.chat.command.commands
|
||||
*/
|
||||
class MuteCommand extends \chat\system\command\AbstractRestrictedCommand {
|
||||
public $user = null;
|
||||
public $expires = 0;
|
||||
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)))
|
||||
));
|
||||
}
|
||||
class MuteCommand extends \chat\system\command\AbstractSuspensionCommand {
|
||||
const IS_GLOBAL = false;
|
||||
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
<?php
|
||||
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.
|
||||
@ -14,17 +10,7 @@
|
||||
* @package be.bastelstu.chat
|
||||
* @subpackage system.chat.command.commands
|
||||
*/
|
||||
class UnbanCommand extends UnmuteCommand {
|
||||
/**
|
||||
* @see \chat\system\command\commands\UnmuteCommand::executeAction()
|
||||
*/
|
||||
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'));
|
||||
}
|
||||
}
|
||||
class UnbanCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||
const IS_GLOBAL = false;
|
||||
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_BAN;
|
||||
}
|
||||
|
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
|
||||
namespace chat\system\command\commands;
|
||||
use \chat\data\suspension;
|
||||
use \wcf\data\user\User;
|
||||
use \wcf\system\WCF;
|
||||
|
||||
/**
|
||||
* Unmutes a user.
|
||||
@ -13,67 +10,7 @@
|
||||
* @package be.bastelstu.chat
|
||||
* @subpackage system.chat.command.commands
|
||||
*/
|
||||
class UnmuteCommand extends \chat\system\command\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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)))
|
||||
));
|
||||
}
|
||||
class UnmuteCommand extends \chat\system\command\AbstractUnsuspensionCommand {
|
||||
const IS_GLOBAL = false;
|
||||
const SUSPENSION_TYPE = \chat\data\suspension\Suspension::TYPE_MUTE;
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ public function execute(\wcf\data\cronjob\Cronjob $cronjob) {
|
||||
$messageAction->executeAction();
|
||||
$roomAction = new data\room\RoomAction(array(), 'prune');
|
||||
$roomAction->executeAction();
|
||||
$suspensionAction = new data\suspension\SuspensionAction(array(), 'prune');
|
||||
$suspensionAction->executeAction();
|
||||
|
||||
// kill dead users
|
||||
$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 {
|
||||
#main > div {
|
||||
overflow: hidden;
|
||||
@ -28,17 +40,120 @@
|
||||
.transition(padding-top, .2s);
|
||||
.transition(padding-bottom, .2s);
|
||||
|
||||
&.empty {
|
||||
&.empty, &.hidden {
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
border: 0px;
|
||||
padding: 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 {
|
||||
height: 200px;
|
||||
height: 320px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
display: none;
|
||||
@ -55,9 +170,9 @@
|
||||
color: @wcfSelectedColor;
|
||||
}
|
||||
|
||||
> {
|
||||
> .innerMessageContainer {
|
||||
.markContainer {
|
||||
display: table-cell;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,47 +192,138 @@
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&::before {
|
||||
.icon;
|
||||
.icon16;
|
||||
padding: @wcfGapTiny;
|
||||
}
|
||||
|
||||
&:nth-child(even) {
|
||||
> .innerMessageContainer.bubble .innerMessage, .innerMessageContainer.right.bubble .innerMessage {
|
||||
background-color: @wcfContainerAccentBackgroundColor;
|
||||
|
||||
&:after {
|
||||
border-color: transparent @wcfContainerAccentBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> {
|
||||
time, .usernameContainer, .text, .markContainer {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
padding: @wcfGapTiny 0;
|
||||
.messageIcon {
|
||||
float: left;
|
||||
padding: 8px 0 0 4px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
|
||||
.markContainer {
|
||||
display: none;
|
||||
padding: 0;
|
||||
> .innerMessageContainer {
|
||||
padding: 5px 20px 5px 5px;
|
||||
position: relative;
|
||||
|
||||
.userAvatar {
|
||||
float: left;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.innerMessage {
|
||||
margin-left: 46px;
|
||||
padding: 2px 5px 5px;
|
||||
|
||||
time {
|
||||
&::before {
|
||||
content: "[";
|
||||
float: right;
|
||||
}
|
||||
|
||||
> .text {
|
||||
img {
|
||||
max-width: 480px;
|
||||
max-height: 320px;
|
||||
}
|
||||
&::after {
|
||||
content: "]";
|
||||
}
|
||||
}
|
||||
|
||||
.usernameContainer {
|
||||
text-align: right;
|
||||
min-width: 100px;
|
||||
padding-right: @wcfGapSmall;
|
||||
white-space: nowrap;
|
||||
&.bubble {
|
||||
.userAvatar {
|
||||
margin-left: 0;
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 100%;
|
||||
> ul.text {
|
||||
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,
|
||||
userID INT(10) NOT NULL,
|
||||
roomID INT(10) DEFAULT NULL,
|
||||
type TINYINT(3) NOT NULL,
|
||||
type VARCHAR(15) 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 (type),
|
||||
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 (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;
|
||||
|
||||
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 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);
|
||||
|
@ -11,10 +11,32 @@
|
||||
<item name="chat.acp.room.delete.sure"><![CDATA[Wollen Sie den Raum „{$chatRoom}“ wirklich löschen?]]></item>
|
||||
</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">
|
||||
<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.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 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.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.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.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.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 name="wcf.acp.option">
|
||||
@ -59,7 +93,7 @@
|
||||
</category>
|
||||
|
||||
<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.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>
|
||||
@ -68,6 +102,9 @@
|
||||
</category>
|
||||
|
||||
<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.protocol"><![CDATA[Protokoll]]></item>
|
||||
|
||||
@ -100,6 +137,10 @@
|
||||
<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.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 name="chat.header">
|
||||
@ -117,21 +158,21 @@
|
||||
<item name="chat.message.4"><![CDATA[ist jetzt wieder da.]]></item>
|
||||
<!-- 5 = TYPE_MODERATE -->
|
||||
<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.ban"><![CDATA[hat {@$link} bis {@$expires|plainTime} gebannt.]]></item>
|
||||
<item name="chat.message.5.gmute"><![CDATA[hat {@$link} bis {@$expires|plainTime} global geknebelt.]]></item>
|
||||
<item name="chat.message.5.gban"><![CDATA[hat {@$link} bis {@$expires|plainTime} global gebannt.]]></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{if !$reason|empty}: {$reason}{else}.{/if}]]></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{if !$reason|empty}: {$reason}{else}.{/if}]]></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.gunmute"><![CDATA[hat {@$link} global entknebelt.]]></item>
|
||||
<item name="chat.message.5.gunban"><![CDATA[hat {@$link} global entbannt.]]></item>
|
||||
<item name="chat.message.5.ungmute"><![CDATA[hat {@$link} global entknebelt.]]></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>
|
||||
</category>
|
||||
|
||||
<category name="chat.suspension">
|
||||
<item name="chat.suspension.1"><![CDATA[Knebel]]></item>
|
||||
<item name="chat.suspension.2"><![CDATA[Bann]]></item>
|
||||
<item name="chat.suspension.mute"><![CDATA[Knebel]]></item>
|
||||
<item name="chat.suspension.ban"><![CDATA[Bann]]></item>
|
||||
</category>
|
||||
|
||||
<!-- I18N Values -->
|
||||
|
@ -49,7 +49,9 @@
|
||||
<optiontype>textarea</optiontype>
|
||||
<defaultvalue>afk:away
|
||||
col:color
|
||||
msg:whisper</defaultvalue>
|
||||
msg:whisper
|
||||
gunban:ungban
|
||||
gunmute:ungmute</defaultvalue>
|
||||
</option>
|
||||
<!-- general chat options end -->
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<packagedescription><![CDATA[Chat for WoltLab Community Framework™.]]></packagedescription>
|
||||
<packagedescription language="de"><![CDATA[Chat für WoltLab Community Framework™.]]></packagedescription>
|
||||
<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>
|
||||
<license><![CDATA[Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>]]></license>
|
||||
</packageinformation>
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
{include file='headInclude' sandbox=false}
|
||||
{include file='javascriptInclude' application='chat'}
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
//<![CDATA[
|
||||
(function ($, window) {
|
||||
$(function(){
|
||||
@ -15,27 +15,33 @@
|
||||
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
||||
'chat.general.profile': '{lang}chat.general.profile{/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.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
||||
'chat.error.join': '{lang}chat.error.join{/lang}',
|
||||
'chat.error.reload': '{lang}chat.error.reload{/lang}'
|
||||
});
|
||||
|
||||
{event name='beforeInit'}
|
||||
|
||||
// Boot the chat
|
||||
{if MODULE_SMILEY}WCF.TabMenu.init();{/if}
|
||||
new WCF.Message.Smilies();
|
||||
{capture assign='messageTemplate'}{include application='chat' file='message'}{/capture}
|
||||
{capture assign='userTemplate'}{include application='chat' file='userListUser'}{/capture}
|
||||
|
||||
be.bastelstu.Chat.init(
|
||||
{$roomID},
|
||||
{
|
||||
var config = {
|
||||
reloadTime: {@CHAT_RELOADTIME},
|
||||
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('{@$messageTemplate|encodeJS}'),
|
||||
new WCF.Template('{@$userTemplate|encodeJS}')
|
||||
@ -54,36 +60,31 @@
|
||||
})(jQuery, this);
|
||||
//]]>
|
||||
</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>
|
||||
|
||||
<body id="tpl{$templateName|ucfirst}">
|
||||
{capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture}
|
||||
{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>
|
||||
<ul>
|
||||
</ul>
|
||||
@ -93,7 +94,7 @@
|
||||
<fieldset>
|
||||
<dl class="wide" id="timsChatInputContainer">
|
||||
<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>
|
||||
</dd>
|
||||
</dl>
|
||||
@ -105,7 +106,7 @@
|
||||
{include file='messageFormSmilies' wysiwygSelector=''}
|
||||
{/if}
|
||||
|
||||
<nav id="timsChatOptions" class="marginTop buttonGroupNavigation">
|
||||
<nav id="timsChatOptions" class="marginTop jsMobileNavigation buttonGroupNavigation">
|
||||
<span class="invisible">{lang}chat.general.controls{/lang}</span>
|
||||
<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>{*
|
||||
|
@ -35,7 +35,7 @@
|
||||
{@$roomList}
|
||||
</ul>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
//<![CDATA[
|
||||
(function($, window, undefined) {
|
||||
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 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{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'}
|
@ -4,7 +4,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
//<![CDATA[
|
||||
var log = new be.bastelstu.Chat.Log(chat);
|
||||
log.handleMessages([
|
||||
|
@ -1,24 +1,54 @@
|
||||
{literal}
|
||||
<time>{@$formattedTime}</time>
|
||||
<span class="usernameContainer">
|
||||
<span class="username">{*
|
||||
*}{if $type != 7}{*
|
||||
*}{@$formattedUsername}{*
|
||||
*}{else}
|
||||
{if $receiver == WCF.User.userID}
|
||||
{@$formattedUsername}
|
||||
<div class="messageIcon">
|
||||
{if $message.type == $messageTypes.LEAVE || $message.type == $messageTypes.JOIN}
|
||||
<span class="icon icon16 icon-{if $message.type == $messageTypes.LEAVE}signout{else}signin{/if}"></span>
|
||||
{/if}
|
||||
</div>
|
||||
<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}">
|
||||
<div class="userAvatar framed">
|
||||
{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}
|
||||
<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}
|
||||
</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">
|
||||
<input type="checkbox" value="{@$messageID}" />
|
||||
<input type="checkbox" value="{@$message.messageID}" />
|
||||
</span>
|
||||
</div>
|
||||
{/literal}
|
||||
|
@ -104,6 +104,12 @@
|
||||
<defaultvalue>0</defaultvalue>
|
||||
<admindefaultvalue>1</admindefaultvalue>
|
||||
</option>
|
||||
<option name="admin.chat.canManageSuspensions">
|
||||
<categoryname>admin.chat</categoryname>
|
||||
<optiontype>boolean</optiontype>
|
||||
<defaultvalue>0</defaultvalue>
|
||||
<admindefaultvalue>1</admindefaultvalue>
|
||||
</option>
|
||||
</options>
|
||||
</import>
|
||||
</data>
|
Loading…
Reference in New Issue
Block a user