mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2024-10-31 14:10:08 +00:00
Merge remote-tracking branch 'origin/privateChannels'
This commit is contained in:
commit
0be6efa345
@ -33,6 +33,10 @@ exposed by a function if necessary.
|
|||||||
newMessageCount = 0
|
newMessageCount = 0
|
||||||
scrollUpNotifications = off
|
scrollUpNotifications = off
|
||||||
chatSession = Date.now()
|
chatSession = Date.now()
|
||||||
|
userList =
|
||||||
|
current: {}
|
||||||
|
allTime: {}
|
||||||
|
currentRoom = {}
|
||||||
|
|
||||||
errorVisible = false
|
errorVisible = false
|
||||||
inputErrorHidingTimer = null
|
inputErrorHidingTimer = null
|
||||||
@ -113,6 +117,11 @@ Insert the appropriate smiley code into the input when a smiley is clicked.
|
|||||||
$('#smilies').on 'click', 'img', ->
|
$('#smilies').on 'click', 'img', ->
|
||||||
insertText " #{$(@).attr('alt')} "
|
insertText " #{$(@).attr('alt')} "
|
||||||
|
|
||||||
|
Handle private channel menu
|
||||||
|
|
||||||
|
$('#privateChannelsMenu').on 'click', '.privateChannel', ->
|
||||||
|
openPrivateChannel $(@).data 'privateChannelID'
|
||||||
|
|
||||||
Handle submitting the form. The message will be validated by some basic checks, passed to the `submit` eventlisteners
|
Handle submitting the form. The message will be validated by some basic checks, passed to the `submit` eventlisteners
|
||||||
and afterwards sent to the server by an AJAX request.
|
and afterwards sent to the server by an AJAX request.
|
||||||
|
|
||||||
@ -125,7 +134,7 @@ and afterwards sent to the server by an AJAX request.
|
|||||||
return false if text.length is 0
|
return false if text.length is 0
|
||||||
|
|
||||||
unless openChannel is 0
|
unless openChannel is 0
|
||||||
text = "/whisper #{$("#timsChatMessageContainer#{openChannel}").data 'username'}, #{text}"
|
text = "/whisper #{userList.allTime[openChannel].username}, #{text}"
|
||||||
|
|
||||||
# Free the fish!
|
# Free the fish!
|
||||||
do freeTheFish if text.toLowerCase() is '/free the fish'
|
do freeTheFish if text.toLowerCase() is '/free the fish'
|
||||||
@ -190,7 +199,10 @@ The the word the caret is in will be passed to `autocomplete` and replaced if a
|
|||||||
toComplete = '/' + commands[autocomplete.offset++ % commands.length] + ' ' if commands.length isnt 0
|
toComplete = '/' + commands[autocomplete.offset++ % commands.length] + ' ' if commands.length isnt 0
|
||||||
else
|
else
|
||||||
regex = new RegExp "^#{WCF.String.escapeRegExp toComplete}", "i"
|
regex = new RegExp "^#{WCF.String.escapeRegExp toComplete}", "i"
|
||||||
users = (username for user in $('.timsChatUser') when regex.test(username = $(user).data('username')))
|
|
||||||
|
users = [ ]
|
||||||
|
for userID, user of userList.current
|
||||||
|
users.push user.username if regex.test user.username
|
||||||
|
|
||||||
toComplete = users[autocomplete.offset++ % users.length] + ', ' if users.length isnt 0
|
toComplete = users[autocomplete.offset++ % users.length] + ', ' if users.length isnt 0
|
||||||
|
|
||||||
@ -267,7 +279,10 @@ Toggle checkboxes.
|
|||||||
Hide topic container.
|
Hide topic container.
|
||||||
|
|
||||||
$('.jsTopicCloser').on 'click', ->
|
$('.jsTopicCloser').on 'click', ->
|
||||||
|
if $('.timsChatMessageContainer.active').data('userID') is 0
|
||||||
$('#timsChatTopic').addClass 'hidden'
|
$('#timsChatTopic').addClass 'hidden'
|
||||||
|
else
|
||||||
|
closePrivateChannel $('.timsChatMessageContainer.active').data('userID')
|
||||||
|
|
||||||
Visibly mark the message once the associated checkbox is checked.
|
Visibly mark the message once the associated checkbox is checked.
|
||||||
|
|
||||||
@ -438,10 +453,10 @@ Insert the given messages into the chat stream.
|
|||||||
$('.timsChatMessageContainer.active').trigger 'scroll'
|
$('.timsChatMessageContainer.active').trigger 'scroll'
|
||||||
|
|
||||||
for message in messages
|
for message in messages
|
||||||
events.newMessage.fire message
|
|
||||||
|
|
||||||
message.isInPrivateChannel = (String(message.type) is v.config.messageTypes.WHISPER) and ($.wcfIsset("timsChatMessageContainer#{message.receiver}") or $.wcfIsset("timsChatMessageContainer#{message.sender}"))
|
message.isInPrivateChannel = (String(message.type) is v.config.messageTypes.WHISPER) and ($.wcfIsset("timsChatMessageContainer#{message.receiver}") or $.wcfIsset("timsChatMessageContainer#{message.sender}"))
|
||||||
|
|
||||||
|
events.newMessage.fire message
|
||||||
|
|
||||||
createNewMessage = yes
|
createNewMessage = yes
|
||||||
if $('.timsChatMessage:last-child .text').is('ul') and lastMessage isnt null and lastMessage.type in [ 0, 7 ]
|
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
|
if lastMessage.type is message.type and lastMessage.sender is message.sender and lastMessage.receiver is message.receiver and lastMessage.isInPrivateChannel is message.isInPrivateChannel
|
||||||
@ -488,9 +503,12 @@ Rebuild the userlist based on the given `users`.
|
|||||||
|
|
||||||
handleUsers = (users) ->
|
handleUsers = (users) ->
|
||||||
foundUsers = { }
|
foundUsers = { }
|
||||||
|
userList.current = { }
|
||||||
|
|
||||||
for user in users
|
for user in users
|
||||||
do (user) ->
|
do (user) ->
|
||||||
|
userList.current[user.userID] = userList.allTime[user.userID] = user
|
||||||
|
|
||||||
id = "timsChatUser#{user.userID}"
|
id = "timsChatUser#{user.userID}"
|
||||||
|
|
||||||
Move the user to the new position if he was found in the old list.
|
Move the user to the new position if he was found in the old list.
|
||||||
@ -583,6 +601,17 @@ Send out notifications for the given `message`. The number of unread messages wi
|
|||||||
if scrollUpNotifications
|
if scrollUpNotifications
|
||||||
$('.timsChatMessageContainer.active').addClass 'notification'
|
$('.timsChatMessageContainer.active').addClass 'notification'
|
||||||
|
|
||||||
|
if message.isInPrivateChannel
|
||||||
|
if message.sender is WCF.User.userID
|
||||||
|
privateChannelID = message.receiver
|
||||||
|
else
|
||||||
|
privateChannelID = message.sender
|
||||||
|
|
||||||
|
if $('.timsChatMessageContainer.active').data('userID') isnt privateChannelID
|
||||||
|
$("#privateChannel#{privateChannelID}").addClass 'notify'
|
||||||
|
else if $('.timsChatMessageContainer.active').data('userID') isnt 0
|
||||||
|
$("#privateChannel0").addClass 'notify'
|
||||||
|
|
||||||
return if isActive or $('#timsChatNotify').data('status') is 0
|
return if isActive or $('#timsChatNotify').data('status') is 0
|
||||||
|
|
||||||
document.title = v.titleTemplate.fetch
|
document.title = v.titleTemplate.fetch
|
||||||
@ -678,17 +707,19 @@ Joins a room.
|
|||||||
loading = false
|
loading = false
|
||||||
|
|
||||||
$('#timsChatTopic').removeClass 'hidden'
|
$('#timsChatTopic').removeClass 'hidden'
|
||||||
|
currentRoom = data.returnValues
|
||||||
|
currentRoom.roomID = roomID
|
||||||
|
|
||||||
$('#timsChatTopic > .topic').text data.returnValues.topic
|
$('#timsChatTopic > .topic').text currentRoom.topic
|
||||||
if data.returnValues.topic.trim() is ''
|
if currentRoom.topic.trim() is ''
|
||||||
$('#timsChatTopic').addClass 'empty'
|
$('#timsChatTopic').addClass 'empty'
|
||||||
else
|
else
|
||||||
$('#timsChatTopic').removeClass 'empty'
|
$('#timsChatTopic').removeClass 'empty'
|
||||||
|
|
||||||
$('.timsChatMessage').addClass 'unloaded'
|
$('.timsChatMessage').addClass 'unloaded'
|
||||||
|
|
||||||
document.title = v.titleTemplate.fetch data.returnValues
|
document.title = v.titleTemplate.fetch currentRoom
|
||||||
handleMessages data.returnValues.messages
|
handleMessages currentRoom.messages
|
||||||
do getMessages
|
do getMessages
|
||||||
do refreshRoomList
|
do refreshRoomList
|
||||||
failure: ->
|
failure: ->
|
||||||
@ -697,26 +728,76 @@ Joins a room.
|
|||||||
Open private channel
|
Open private channel
|
||||||
|
|
||||||
openPrivateChannel = (userID) ->
|
openPrivateChannel = (userID) ->
|
||||||
unless $.wcfIsset "timsChatMessageContainer#{userID}"
|
userID = parseInt userID
|
||||||
return unless $.wcfIsset "timsChatUser#{userID}"
|
|
||||||
|
|
||||||
div = $('<div>')
|
console.log "Opening private channel #{userID}"
|
||||||
|
|
||||||
|
unless $.wcfIsset "timsChatMessageContainer#{userID}"
|
||||||
|
return unless userList.allTime[userID]?
|
||||||
|
|
||||||
|
div = $ '<div>'
|
||||||
div.attr 'id', "timsChatMessageContainer#{userID}"
|
div.attr 'id', "timsChatMessageContainer#{userID}"
|
||||||
|
div.data 'userID', userID
|
||||||
div.addClass 'timsChatMessageContainer'
|
div.addClass 'timsChatMessageContainer'
|
||||||
div.addClass 'marginTop'
|
div.addClass 'marginTop'
|
||||||
div.addClass 'container'
|
div.addClass 'container'
|
||||||
div.data 'username', $("#timsChatUser#{userID}").data 'username'
|
|
||||||
div.wrapInner '<ul>'
|
div.wrapInner '<ul>'
|
||||||
$('#timsChatMessageContainer0').after div
|
$('#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').removeClass 'active'
|
||||||
$("#timsChatMessageContainer#{userID}").addClass 'active'
|
$("#timsChatMessageContainer#{userID}").addClass 'active'
|
||||||
|
$("#privateChannel#{userID}").addClass('active').removeClass 'notify'
|
||||||
openChannel = userID
|
openChannel = userID
|
||||||
|
|
||||||
Close private channel
|
Close private channel
|
||||||
|
|
||||||
closePrivateChannel = (userID) ->
|
closePrivateChannel = (userID) ->
|
||||||
do $("#timsChatMessageContainer#{userID}").remove unless userID is 0
|
unless userID is 0
|
||||||
|
do $("#privateChannel#{userID}").remove
|
||||||
|
do $("#timsChatMessageContainer#{userID}").remove
|
||||||
|
|
||||||
|
if $('#privateChannelsMenu li').length <= 1
|
||||||
|
$('#privateChannelsMenu').removeClass 'shown'
|
||||||
|
|
||||||
openPrivateChannel 0
|
openPrivateChannel 0
|
||||||
|
|
||||||
Bind the given callback to the given event.
|
Bind the given callback to the given event.
|
||||||
|
@ -58,6 +58,100 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#privateChannelsMenu {
|
||||||
|
.transition(opacity, .2s);
|
||||||
|
.marginTop;
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&.shown {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 130;
|
||||||
|
|
||||||
|
~ .timsChatMessageContainer {
|
||||||
|
margin-left: 35px;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
> li:first-child {
|
||||||
|
> .userAvatar.framed {
|
||||||
|
img, > canvas, > .icon {
|
||||||
|
border-radius: @wcfContainerBorderRadius 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> li:last-child {
|
||||||
|
> .userAvatar.framed {
|
||||||
|
img, > canvas, > .icon {
|
||||||
|
border-radius: 0 0 0 @wcfContainerBorderRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> li {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
background-color: @wcfContainerBackgroundColor;
|
||||||
|
|
||||||
|
> .userAvatar, .userAvatar > .icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .userAvatar {
|
||||||
|
&.large {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.framed {
|
||||||
|
> .icon {
|
||||||
|
background-color: @wcfContentBackgroundColor;
|
||||||
|
border: 1px solid @wcfContainerBorderColor;
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
> .userAvatar {
|
||||||
|
&.large {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.framed {
|
||||||
|
> img, > canvas, > .icon {
|
||||||
|
border-right-color: @wcfContentBackgroundColor;
|
||||||
|
|
||||||
|
border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.notify {
|
||||||
|
> .userAvatar {
|
||||||
|
> * {
|
||||||
|
// TODO
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.timsChatMessageContainer {
|
.timsChatMessageContainer {
|
||||||
height: 320px;
|
height: 320px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
@ -137,6 +137,10 @@
|
|||||||
<item name="chat.general.information"><![CDATA[Information]]></item>
|
<item name="chat.general.information"><![CDATA[Information]]></item>
|
||||||
<item name="chat.general.information.chatUpdate"><![CDATA[Der Chat wurde aktualisiert. Bitte laden Sie die Seite neu, da es sonst zu Fehlern kommen kann.]]></item>
|
<item name="chat.general.information.chatUpdate"><![CDATA[Der Chat wurde aktualisiert. Bitte laden Sie die Seite neu, da es sonst zu Fehlern kommen kann.]]></item>
|
||||||
<item name="chat.general.information.suspension"><![CDATA[{lang}chat.suspension.{$suspension->type}{/lang} ({if $room}{$room}{else}{lang}chat.room.global{/lang}{/if})]]></item>
|
<item name="chat.general.information.suspension"><![CDATA[{lang}chat.suspension.{$suspension->type}{/lang} ({if $room}{$room}{else}{lang}chat.room.global{/lang}{/if})]]></item>
|
||||||
|
|
||||||
|
<item name="chat.general.privateChannelTopic"><![CDATA[{literal}Sie befinden sich in einem privaten Kanal mit „{$username}“, um diesen zu schließen, klicken Sie einfach auf das Kreuz rechts.{/literal}]]></item>
|
||||||
|
<item name="chat.general.closePrivateChannel"><![CDATA[Privaten Kanal schließen]]></item>
|
||||||
|
<item name="chat.general.closeTopic"><![CDATA[Thema ausblenden]]></item>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="chat.header">
|
<category name="chat.header">
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
||||||
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
||||||
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
||||||
|
'chat.general.privateChannelTopic': '{lang}chat.general.privateChannelTopic{/lang}',
|
||||||
|
'chat.general.closePrivateChannel': '{lang}chat.general.closePrivateChannel{/lang}',
|
||||||
|
'chat.general.closeTopic': '{lang}chat.general.closeTopic{/lang}',
|
||||||
'chat.error.onMessageLoad': '{lang}chat.error.onMessageLoad{/lang}',
|
'chat.error.onMessageLoad': '{lang}chat.error.onMessageLoad{/lang}',
|
||||||
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
||||||
'chat.error.join': '{lang}chat.error.join{/lang}',
|
'chat.error.join': '{lang}chat.error.join{/lang}',
|
||||||
@ -71,11 +74,24 @@
|
|||||||
{include file='header' sandbox=false sidebarOrientation='right'}
|
{include file='header' sandbox=false sidebarOrientation='right'}
|
||||||
|
|
||||||
<div id="timsChatTopic" class="container{if $room->topic|language === ''} empty{/if}">
|
<div id="timsChatTopic" class="container{if $room->topic|language === ''} empty{/if}">
|
||||||
<span class="icon icon16 icon-remove jsTopicCloser"></span>
|
<span class="icon icon16 icon-remove jsTopicCloser jsTooltip" title="{lang}chat.general.closeTopic{/lang}"></span>
|
||||||
<span class="topic">{$room->topic|language}</span>
|
<span class="topic">{$room->topic|language}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="timsChatMessageContainer0" class="timsChatMessageContainer marginTop container active">
|
<div id="privateChannelsMenu">
|
||||||
|
<ul>
|
||||||
|
<li id="privateChannel0" class="privateChannel active" data-private-channel-id="0">
|
||||||
|
<span class="userAvatar framed small">
|
||||||
|
<span class="icon icon16 icon-comment-alt jsTooltip" title="{lang}chat.general.room{/lang}"></span>
|
||||||
|
</span>
|
||||||
|
<span class="userAvatar framed large">
|
||||||
|
<span class="icon icon32 icon-comment-alt jsTooltip" title="{lang}chat.general.room{/lang}"></span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="timsChatMessageContainer0" class="timsChatMessageContainer marginTop container active" data-user-id="0">
|
||||||
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
||||||
<ul>
|
<ul>
|
||||||
</ul>
|
</ul>
|
||||||
|
Loading…
Reference in New Issue
Block a user