mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2024-10-31 14:10:08 +00:00
Rewrite frontend
With this commit pretty much the whole frontend has been rewritten. This should hopefully fix most of the issues in “exotic” styles. The changes include: - Overall cleanup - Better adaption to the WCF design - Reworked private channels menu - Reworked sidebar (may change later, currently the heights of the elements are hardcoded and not dynamic) - Working user action menu - Fixed auto scrolling - Better visual notifications - This software does not contain any easter eggs - No penguins were harmed in the production of this software Todo: - Fullscreen mode - Some language variables
This commit is contained in:
parent
4d208f8893
commit
92ed075076
@ -6,7 +6,7 @@ everything that happens in the GUI of **Tims Chat**.
|
||||
|
||||
### Copyright Information
|
||||
# @author Tim Düsterhus
|
||||
# @copyright 2010-2013 Tim Düsterhus
|
||||
# @copyright 2010-2014 Tim Düsterhus
|
||||
# @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
# @package be.bastelstu.chat
|
||||
###
|
||||
@ -73,7 +73,7 @@ exposed by a function if necessary.
|
||||
Initialize **Tims Chat**. Bind needed DOM events and initialize data structures.
|
||||
|
||||
initialized = false
|
||||
init = (roomID, config, titleTemplate, messageTemplate, userTemplate) ->
|
||||
init = (roomID, config, titleTemplate, messageTemplate, userTemplate, userMenuTemplate) ->
|
||||
return false if initialized
|
||||
initialized = true
|
||||
|
||||
@ -81,6 +81,7 @@ Initialize **Tims Chat**. Bind needed DOM events and initialize data structures.
|
||||
v.titleTemplate = titleTemplate
|
||||
v.messageTemplate = messageTemplate
|
||||
v.userTemplate = userTemplate
|
||||
v.userMenuTemplate = userMenuTemplate
|
||||
|
||||
console.log 'Initializing'
|
||||
|
||||
@ -117,7 +118,8 @@ Insert the appropriate smiley code into the input when a smiley is clicked.
|
||||
|
||||
Handle private channel menu
|
||||
|
||||
$('#privateChannelsMenu').on 'click', '.privateChannel', -> openPrivateChannel $(@).data 'privateChannelID'
|
||||
$('#timsChatMessageTabMenu > .tabMenu').on 'click', '.timsChatMessageTabMenuAnchor', ->
|
||||
openPrivateChannel $(@).data 'userID'
|
||||
|
||||
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.
|
||||
@ -217,9 +219,24 @@ Reset autocompleter to default status, when the input is `click`ed, as the posit
|
||||
value: null
|
||||
caret: null
|
||||
|
||||
Bind user menu functions
|
||||
|
||||
$('#dropdownMenuContainer').on 'click', '.jsTimsChatUserMenuWhisper', ->
|
||||
command = "/whisper #{userList.current[$(@).parents('ul').data 'userID'].username}, "
|
||||
return if $('#timsChatInput').val().match(new RegExp WCF.String.escapeRegExp("^#{command}"), 'i')
|
||||
|
||||
insertText command, prepend: yes
|
||||
|
||||
$('#dropdownMenuContainer').on 'click', '.jsTimsChatUserMenuQuery', -> openPrivateChannel $(@).parents('ul').data 'userID'
|
||||
$('#dropdownMenuContainer').on 'click', '.jsTimsChatUserMenuBan', ->
|
||||
command = "/ban #{userList.current[$(@).parents('ul').data 'userID'].username}, "
|
||||
return if $('#timsChatInput').val().match(new RegExp WCF.String.escapeRegExp("^#{command}"), 'i')
|
||||
|
||||
insertText command, prepend: yes
|
||||
|
||||
Refresh the room list when the associated button is `click`ed.
|
||||
|
||||
$('#timsChatRoomList button').click -> do refreshRoomList
|
||||
$('#timsChatRoomListReloadButton').click -> do refreshRoomList
|
||||
|
||||
Clear the chat by removing every single message once the clear button is `clicked`.
|
||||
|
||||
@ -247,9 +264,9 @@ Mark smilies as disabled when they are disabled.
|
||||
|
||||
$('#timsChatSmilies').click (event) ->
|
||||
if $(@).data 'status'
|
||||
$('#smilies').removeClass 'disabled'
|
||||
$('#smilies').removeClass 'invisible'
|
||||
else
|
||||
$('#smilies').addClass 'disabled'
|
||||
$('#smilies').addClass 'invisible'
|
||||
|
||||
Toggle fullscreen mode.
|
||||
|
||||
@ -272,11 +289,11 @@ Toggle checkboxes.
|
||||
|
||||
Hide topic container.
|
||||
|
||||
$('.jsTopicCloser').on 'click', ->
|
||||
if $('.timsChatMessageContainer.active').data('userID') is 0
|
||||
$('#timsChatTopic').addClass 'hidden'
|
||||
else
|
||||
closePrivateChannel $('.timsChatMessageContainer.active').data('userID')
|
||||
$('#timsChatTopicCloser').on 'click', -> $('#timsChatTopic').addClass 'invisible'
|
||||
|
||||
Close private channels
|
||||
|
||||
$('#timsChatMessageTabMenu').on 'click', '.jsChannelCloser', -> closePrivateChannel $(@).parent().data 'userID'
|
||||
|
||||
Visibly mark the message once the associated checkbox is checked.
|
||||
|
||||
@ -289,27 +306,20 @@ Visibly mark the message once the associated checkbox is checked.
|
||||
Scroll down when autoscroll is being activated.
|
||||
|
||||
$('#timsChatAutoscroll').click (event) ->
|
||||
if $('#timsChatAutoscroll').data 'status'
|
||||
if $(@).data 'status'
|
||||
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop 'scrollHeight'
|
||||
|
||||
scrollUpNotifications = off
|
||||
$("#timsChatMessageTabMenu > .tabMenu > ul > li.ui-state-active").removeClass 'notify'
|
||||
$(".timsChatMessageContainer.active").removeClass 'notify'
|
||||
else
|
||||
scrollUpNotifications = on
|
||||
|
||||
Bind scroll event on predefined message containers
|
||||
|
||||
$('.timsChatMessageContainer.active').on 'scroll', (event) ->
|
||||
event.stopPropagation();
|
||||
|
||||
element = $ @
|
||||
scrollTop = element.scrollTop()
|
||||
scrollHeight = element.prop 'scrollHeight'
|
||||
height = element.height()
|
||||
|
||||
if scrollTop < scrollHeight - height - 25
|
||||
if $('#timsChatAutoscroll').data('status') is 1
|
||||
scrollUpNotifications = on
|
||||
do $('#timsChatAutoscroll').click
|
||||
|
||||
if scrollTop > scrollHeight - height - 10
|
||||
if $('#timsChatAutoscroll').data('status') is 0
|
||||
scrollUpNotifications = off
|
||||
$(@).removeClass 'notification'
|
||||
do $('#timsChatAutoscroll').click
|
||||
do event.stopPropagation
|
||||
handleScroll event
|
||||
|
||||
Enable duplicate tab detection.
|
||||
|
||||
@ -384,35 +394,85 @@ Free the fish.
|
||||
freeTheFish = ->
|
||||
return if $.wcfIsset 'fish'
|
||||
console.warn 'Freeing the fish'
|
||||
fish = $ """<div id="fish">#{WCF.String.escapeHTML('><((((\u00B0>')}</div>"""
|
||||
fish = $ """<div id="fish"><span></span></div>"""
|
||||
fish.direction = 'right'
|
||||
|
||||
fish.css
|
||||
position: 'fixed'
|
||||
top: '50%'
|
||||
left: '50%'
|
||||
color: 'black'
|
||||
textShadow: '1px 1px white'
|
||||
zIndex: 9999
|
||||
zIndex: 0x7FFFFFFF
|
||||
textShadow: '1px 1px rgb(0, 0, 0)'
|
||||
|
||||
fish.appendTo $ 'body'
|
||||
pe.fish = new WCF.PeriodicalExecuter ->
|
||||
left = Math.random() * 100 - 50
|
||||
top = Math.random() * 100 - 50
|
||||
fish = $ '#fish'
|
||||
|
||||
left *= -1 unless fish.width() < (fish.position().left + left) < ($(window).width() - fish.width())
|
||||
top *= -1 unless fish.height() < (fish.position().top + top) < ($(window).height() - fish.height())
|
||||
fish.colors = ['78C5D6', '459ba8', '79C267', 'C5D647', 'F5D63D', 'F28C33', 'E868A2', 'BF62A6']
|
||||
fish.colorIndex = 0
|
||||
|
||||
if left > 0
|
||||
fish.text '><((((\u00B0>' if left > 0
|
||||
else if left < 0
|
||||
fish.text '<\u00B0))))><'
|
||||
fish.texts =
|
||||
right: '><((((\u00B0>'
|
||||
left: '<\u00B0))))><'
|
||||
fish.fishes = {}
|
||||
|
||||
Pre build fishes, this allows for faster animation
|
||||
|
||||
$.each fish.texts, (key, value) ->
|
||||
fish.fishes[key] = []
|
||||
index = 0
|
||||
|
||||
while index < value.length
|
||||
html = $ '<span/>'
|
||||
i = 0
|
||||
$(value.split '').each (key, value) ->
|
||||
$("<span>#{value}</span>").css
|
||||
color: '#' + fish.colors[(i++ + index) % fish.colors.length]
|
||||
textShadow: '1px 1px rgb(0, 0, 0)'
|
||||
.appendTo html
|
||||
fish.fishes[key][index++] = html
|
||||
return
|
||||
|
||||
fish.find('> span').replaceWith fish.fishes[fish.direction][0]
|
||||
|
||||
fish.updateRainbowText = (key, value) ->
|
||||
key = key || fish.direction
|
||||
return unless fish.fishes[key]? || not fish.texts[key]?
|
||||
value = value || fish.colorIndex++ % fish.texts[key].length
|
||||
|
||||
fish.find('> span').replaceWith fish.fishes[key][value]
|
||||
|
||||
fish.pePos = new WCF.PeriodicalExecuter ->
|
||||
loops = 0
|
||||
loop
|
||||
++loops
|
||||
|
||||
left = Math.random() * 300 - 150
|
||||
top = Math.random() * 300 - 150
|
||||
|
||||
if (fish.position().top + top) > 0 and (fish.position().left + left + fish.width()) < $(window).width() and (fish.position().top + top + fish.height()) < $(window).height() and (fish.position().left + left) > 0
|
||||
break
|
||||
else if loops is 10
|
||||
console.log 'Magicarp used Splash for the 10th time in a row - it fainted!'
|
||||
fish.css
|
||||
'top': '50%'
|
||||
'left': '50%'
|
||||
break
|
||||
|
||||
if left > 0 and fish.text() isnt '><((((\u00B0>'
|
||||
fish.direction = 'right'
|
||||
fish.updateRainbowText null, fish.colorIndex % fish.texts.right.length
|
||||
else if left < 0 and fish.text() isnt '<\u00B0))))><'
|
||||
fish.direction = 'left'
|
||||
fish.updateRainbowText null, fish.colorIndex % fish.texts.left.length
|
||||
|
||||
fish.animate
|
||||
top: (fish.position().top + top)
|
||||
left: (fish.position().left + left)
|
||||
, 1e3
|
||||
, 1.5e3
|
||||
, 1.2e3
|
||||
|
||||
fish.peColor = new WCF.PeriodicalExecuter ->
|
||||
do fish.updateRainbowText
|
||||
, .125e3
|
||||
|
||||
Fetch new messages from the server and pass them to `handleMessages`. The userlist will be passed to `handleUsers`.
|
||||
`remainingFailures` will be decreased on failure and message loading will be entirely disabled once it reaches zero.
|
||||
@ -446,15 +506,13 @@ Prevent loading messages in parallel.
|
||||
Insert the given messages into the chat stream.
|
||||
|
||||
handleMessages = (messages) ->
|
||||
$('.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
|
||||
|
||||
createNewMessage = yes
|
||||
if $('.timsChatMessage:last-child .text').is('ul') and lastMessage isnt null and lastMessage.type in [ 0, 7 ]
|
||||
if $('.timsChatMessage:last-child .timsChatText').is('ul') and lastMessage isnt null and lastMessage.type in [ v.config.messageTypes.NORMAL, v.config.messageTypes.WHISPER ]
|
||||
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
|
||||
|
||||
@ -490,11 +548,34 @@ Insert the given messages into the chat stream.
|
||||
else
|
||||
messageContainerID = 0
|
||||
|
||||
$("#timsChatMessageContainer#{messageContainerID} .timsChatMessage:last-child .text").append $(output).find('.text li:last-child')
|
||||
$("#timsChatMessageContainer#{messageContainerID} .timsChatMessage:last-child .timsChatText").append $(output).find('.timsChatText li:last-child')
|
||||
|
||||
lastMessage = message
|
||||
|
||||
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop('scrollHeight') if $('#timsChatAutoscroll').data('status') is 1
|
||||
|
||||
Handles scroll event of message containers
|
||||
|
||||
handleScroll = (event) ->
|
||||
element = $ event.target
|
||||
|
||||
if element.hasClass 'active'
|
||||
scrollTop = element.scrollTop()
|
||||
scrollHeight = element.prop 'scrollHeight'
|
||||
height = element.innerHeight()
|
||||
|
||||
if scrollTop < scrollHeight - height - 25
|
||||
if $('#timsChatAutoscroll').data('status') is 1
|
||||
scrollUpNotifications = on
|
||||
do $('#timsChatAutoscroll').click
|
||||
|
||||
if scrollTop > scrollHeight - height - 10
|
||||
if $('#timsChatAutoscroll').data('status') is 0
|
||||
scrollUpNotifications = off
|
||||
$("#timsChatMessageTabMenu > .tabMenu > ul > li.ui-state-active").removeClass 'notify'
|
||||
$(".timsChatMessageContainer.active").removeClass 'notify'
|
||||
do $('#timsChatAutoscroll').click
|
||||
|
||||
Rebuild the userlist based on the given `users`.
|
||||
|
||||
handleUsers = (users) ->
|
||||
@ -545,14 +626,7 @@ 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>'
|
||||
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
|
||||
menu = $(v.userMenuTemplate.fetch user)
|
||||
|
||||
if menu.find('li').length
|
||||
li.append menu
|
||||
@ -560,7 +634,6 @@ Build HTML of the user and insert it into the list, if the users was not found i
|
||||
li.addClass 'dropdown'
|
||||
|
||||
li.appendTo $ '#timsChatUserList > ul'
|
||||
|
||||
foundUsers[id] = true
|
||||
|
||||
Remove all users that left the chat.
|
||||
@ -578,12 +651,17 @@ Insert the given `text` into the input. If `options.append` is true the given `t
|
||||
the existing text. If `options.submit` is true the message will be sent to the server afterwards.
|
||||
|
||||
insertText = (text, options = { }) ->
|
||||
options.append = false if options.prepend? and options.prepend and not options.append?
|
||||
|
||||
options = $.extend
|
||||
prepend: false
|
||||
append: true
|
||||
submit: false
|
||||
, options
|
||||
|
||||
text = text + $('#timsChatInput').val() if options.prepend
|
||||
text = $('#timsChatInput').val() + text if options.append
|
||||
|
||||
$('#timsChatInput').val text
|
||||
do $('#timsChatInput').keyup
|
||||
|
||||
@ -595,19 +673,21 @@ the existing text. If `options.submit` is true the message will be sent to the s
|
||||
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) ->
|
||||
return if message.sender is WCF.User.userID
|
||||
|
||||
if scrollUpNotifications
|
||||
$('.timsChatMessageContainer.active').addClass 'notification'
|
||||
$("#timsChatMessageTabMenu > .tabMenu > ul > li.ui-state-active").addClass 'notify'
|
||||
$(".timsChatMessageContainer.active").addClass 'notify'
|
||||
|
||||
if message.isInPrivateChannel
|
||||
if message.sender is WCF.User.userID
|
||||
privateChannelID = message.receiver
|
||||
else
|
||||
privateChannelID = message.sender
|
||||
id = if message.sender is WCF.User.userID then message.receiver else message.sender
|
||||
|
||||
if $('.timsChatMessageContainer.active').data('userID') isnt privateChannelID
|
||||
$("#privateChannel#{privateChannelID}").addClass 'notify'
|
||||
if $('.timsChatMessageContainer.active').data('userID') isnt id
|
||||
$("#timsChatMessageTabMenuAnchor#{id}").parent().addClass 'notify'
|
||||
$("#timsChatMessageContainer#{id}").addClass 'notify'
|
||||
else if $('.timsChatMessageContainer.active').data('userID') isnt 0
|
||||
$("#privateChannel0").addClass 'notify'
|
||||
$("#timsChatMessageTabMenuAnchor0").parent().addClass 'notify'
|
||||
$("#timsChatMessageContainer0").addClass 'notify'
|
||||
|
||||
return if isActive or $('#timsChatNotify').data('status') is 0
|
||||
|
||||
@ -645,8 +725,9 @@ Fetch the roomlist from the server and update it in the GUI.
|
||||
|
||||
for room in data.returnValues
|
||||
li = $ '<li></li>'
|
||||
li.addClass('timsChatRoom').data('roomID', room.roomID)
|
||||
li.addClass 'active' if room.active
|
||||
$("""<a href="#{room.link}">#{WCF.String.escapeHTML(room.title)} <span class="badge">#{WCF.String.formatNumeric room.userCount}</span></a>""").addClass('timsChatRoom').data('roomID', room.roomID).appendTo li
|
||||
$("""<a href="#{room.link}">#{WCF.String.escapeHTML(room.title)}</a> <span class="badge">#{WCF.String.formatNumeric room.userCount}</span>""").appendTo li
|
||||
$('#timsChatRoomList ul').append li
|
||||
|
||||
if window.history?.replaceState?
|
||||
@ -702,7 +783,7 @@ Joins a room.
|
||||
success: (data) ->
|
||||
loading = false
|
||||
|
||||
$('#timsChatTopic').removeClass 'hidden'
|
||||
$('#timsChatTopic').removeClass 'invisible'
|
||||
currentRoom = data.returnValues
|
||||
currentRoom.roomID = roomID
|
||||
|
||||
@ -734,66 +815,72 @@ Open private channel
|
||||
div = $ '<div>'
|
||||
div.attr 'id', "timsChatMessageContainer#{userID}"
|
||||
div.data 'userID', userID
|
||||
div.addClass 'tabMenuContent'
|
||||
div.addClass 'timsChatMessageContainer'
|
||||
div.addClass 'marginTop'
|
||||
div.addClass 'container'
|
||||
div.wrapInner '<ul>'
|
||||
div.addClass 'containerPadding'
|
||||
div.wrapInner "<ul></ul>"
|
||||
div.on 'scroll', (event) ->
|
||||
do event.stopPropagation
|
||||
handleScroll event
|
||||
|
||||
$('#timsChatMessageContainer0').after div
|
||||
|
||||
$('.privateChannel').removeClass 'active'
|
||||
|
||||
if userID isnt 0
|
||||
$('#timsChatTopic').removeClass 'hidden empty'
|
||||
$('#timsChatTopic').removeClass 'empty'
|
||||
$('#timsChatTopic > .topic').html WCF.Language.get 'chat.general.privateChannelTopic', {username: userList.allTime[userID].username}
|
||||
$('#timsChatTopic > .jsTopicCloser').attr 'title', WCF.Language.get 'chat.general.closePrivateChannel'
|
||||
$('#timsChatMessageTabMenu').removeClass 'singleTab'
|
||||
|
||||
unless $.wcfIsset "privateChannel#{userID}"
|
||||
unless $.wcfIsset "timsChatMessageTabMenuAnchor#{userID}"
|
||||
li = $ '<li>'
|
||||
li.attr 'id', "privateChannel#{userID}"
|
||||
li.data 'privateChannelID', userID
|
||||
li.addClass 'privateChannel'
|
||||
|
||||
span = $ '<span class="userAvatar framed" />'
|
||||
anchor = $ """<a id="timsChatMessageTabMenuAnchor#{userID}" class="timsChatMessageTabMenuAnchor" href="#{window.location.toString().replace /#.+$/, ''}#timsChatMessageContainer#{userID}" />"""
|
||||
anchor.data 'userID', userID
|
||||
|
||||
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 = $('<span class="userAvatar framed" />').wrapInner avatar
|
||||
avatar.append "<span>#{userList.allTime[userID].username}</span>"
|
||||
|
||||
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'
|
||||
anchor.wrapInner avatar
|
||||
anchor.prepend '<span class="icon icon16 icon-warning-sign notifyIcon"></span>'
|
||||
anchor.append """<span class="jsChannelCloser icon icon16 icon-remove jsTooltip" title="#{WCF.Language.get('chat.global.closePrivateChannel')}" />"""
|
||||
|
||||
$('#privateChannelsMenu ul').append li
|
||||
li.append anchor
|
||||
|
||||
$('#privateChannelsMenu').addClass 'shown'
|
||||
$('#timsChatMessageTabMenu > .tabMenu > ul').append li
|
||||
$('#timsChatMessageTabMenu').wcfTabs 'refresh'
|
||||
WCF.System.FlexibleMenu.rebuild $('#timsChatMessageTabMenu > .tabMenu').attr 'id'
|
||||
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'
|
||||
$("#timsChatMessageTabMenuAnchor#{userID}").parent().removeClass 'notify'
|
||||
$("#timsChatMessageContainer#{userID}").removeClass 'notify'
|
||||
if $('#timsChatAutoscroll').data('status')
|
||||
do $('#timsChatAutoscroll').click
|
||||
scrollUpNotifications = on
|
||||
|
||||
$('#timsChatMessageTabMenu').wcfTabs 'select', $("#timsChatMessageTabMenuAnchor#{userID}").parent().index()
|
||||
do WCF.DOMNodeInsertedHandler.execute
|
||||
|
||||
openChannel = userID
|
||||
|
||||
Close private channel
|
||||
|
||||
closePrivateChannel = (userID) ->
|
||||
unless userID is 0
|
||||
do $("#privateChannel#{userID}").remove
|
||||
do $("#timsChatMessageTabMenuAnchor#{userID}").parent().remove
|
||||
do $("#timsChatMessageContainer#{userID}").remove
|
||||
$('#timsChatMessageTabMenu').wcfTabs 'refresh'
|
||||
WCF.System.FlexibleMenu.rebuild $('#timsChatMessageTabMenu > .tabMenu').wcfIdentify()
|
||||
|
||||
if $('#privateChannelsMenu li').length <= 1
|
||||
$('#privateChannelsMenu').removeClass 'shown'
|
||||
if $('#timsChatMessageTabMenu > .tabMenu > ul > li').length <= 1
|
||||
$('#timsChatMessageTabMenu').addClass 'singleTab'
|
||||
|
||||
openPrivateChannel 0
|
||||
|
||||
@ -965,7 +1052,7 @@ Create a message containing the uploaded attachment
|
||||
unless parseInt(data.returnValues.attachments[internalFileID].isImage) is 0
|
||||
link.addClass('jsImageViewer')
|
||||
|
||||
if !data.returnValues.attachments[internalFileID].tinyURL
|
||||
unless data.returnValues.attachments[internalFileID].tinyURL
|
||||
li.find('.box32 > div.attachmentImageContainer > .icon-paper-clip').replaceWith $("""<img src="#{data.returnValues.attachments[internalFileID].url}'" alt="" class="attachmentTinyThumbnail" style="width: 32px; height: 32px;" />""")
|
||||
|
||||
li.find('.attachmentTinyThumbnail').wrap link
|
||||
|
@ -1,11 +1,42 @@
|
||||
/**
|
||||
* Styles for Tims Chat
|
||||
* Styles for Tim’s Chat
|
||||
*
|
||||
* @author Tim Düsterhus, Maximilian Mader
|
||||
* @copyright 2010-2013 Tim Düsterhus
|
||||
* @copyright 2010-2014 Tim Düsterhus
|
||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||
* @package be.bastelstu.chat
|
||||
*/
|
||||
|
||||
@-webkit-keyframes timsChatNotify {
|
||||
from {
|
||||
border-color: @wcfContainerBorderColor;
|
||||
}
|
||||
|
||||
to {
|
||||
border-color: @wcfInputHoverBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes timsChatNotify {
|
||||
from {
|
||||
border-color: @wcfContainerBorderColor;
|
||||
}
|
||||
|
||||
to {
|
||||
border-color: @wcfInputHoverBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes timsChatNotify {
|
||||
from {
|
||||
border-color: @wcfContainerBorderColor;
|
||||
}
|
||||
|
||||
to {
|
||||
border-color: @wcfInputHoverBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes timsChatNotify {
|
||||
from {
|
||||
border-color: @wcfContainerBorderColor;
|
||||
@ -16,365 +47,400 @@
|
||||
}
|
||||
}
|
||||
|
||||
.__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;
|
||||
}
|
||||
|
||||
// only apply styles to Tim’s Chat
|
||||
#tplChat {
|
||||
#timsChatTopic {
|
||||
padding: @wcfGapTiny;
|
||||
.transition(height, .2s);
|
||||
.transition(padding-top, .2s);
|
||||
.transition(padding-bottom, .2s);
|
||||
#content {
|
||||
// styles related to the topic container
|
||||
#timsChatTopic {
|
||||
position: relative;
|
||||
|
||||
&.empty, &.hidden {
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
border: 0px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
#timsChatTopicCloser {
|
||||
position: absolute;
|
||||
top: @wcfGapSmall;
|
||||
right: @wcfGapSmall;
|
||||
cursor: pointer;
|
||||
|
||||
.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;
|
||||
&:hover {
|
||||
color: @wcfLinkColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> ul {
|
||||
text-align: right;
|
||||
#timsChatMessageTabMenu {
|
||||
&.singleTab {
|
||||
> nav.tabMenu {
|
||||
// hide tab menu when single tabbed
|
||||
// this is “a bit” hacky
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
> li:first-child {
|
||||
> .userAvatar.framed {
|
||||
img, > canvas, > .icon {
|
||||
border-radius: @wcfContainerBorderRadius 0 0 0;
|
||||
// overwrite WCF margin overwrite on tab menu content with WCF marginTop like margin
|
||||
// this is “a bit” hacky
|
||||
margin-top: @wcfGapMedium !important;
|
||||
|
||||
> .tabMenuContent {
|
||||
}
|
||||
|
||||
.timsChatMessageContainer {
|
||||
&.notify {
|
||||
-webkit-animation-duration: .2s;
|
||||
-webkit-animation-name: timsChatNotify;
|
||||
-webkit-animation-iteration-count: 5;
|
||||
-webkit-animation-direction: alternate;
|
||||
-webkit-animation-timing-function: linear;
|
||||
|
||||
-moz-animation-duration: .2s;
|
||||
-moz-animation-name: timsChatNotify;
|
||||
-moz-animation-iteration-count: 5;
|
||||
-moz-animation-direction: alternate;
|
||||
-moz-animation-timing-function: linear;
|
||||
|
||||
-o-animation-duration: .2s;
|
||||
-o-animation-name: timsChatNotify;
|
||||
-o-animation-iteration-count: 5;
|
||||
-o-animation-direction: alternate;
|
||||
-o-animation-timing-function: linear;
|
||||
|
||||
animation-duration: .2s;
|
||||
animation-name: timsChatNotify;
|
||||
animation-iteration-count: 5;
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: linear;
|
||||
|
||||
border-color: @wcfInputHoverBorderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> li:last-child {
|
||||
> .userAvatar.framed {
|
||||
img, > canvas, > .icon {
|
||||
border-radius: 0 0 0 @wcfContainerBorderRadius;
|
||||
}
|
||||
}
|
||||
}
|
||||
> nav.tabMenu {
|
||||
> ul {
|
||||
> li {
|
||||
> a {
|
||||
.notifyIcon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> li {
|
||||
margin-bottom: -1px;
|
||||
background-color: @wcfContainerBackgroundColor;
|
||||
> .icon, img {
|
||||
// fix vertical alignment of images in tabs
|
||||
vertical-align: middle;
|
||||
margin-right: @wcfGapTiny;
|
||||
}
|
||||
|
||||
> .userAvatar, .userAvatar > .icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
> .userAvatar {
|
||||
&.large {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.small {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
> .userAvatar {
|
||||
&.large {
|
||||
display: block;
|
||||
// styles related to the close button of private channels in tabs
|
||||
.jsChannelCloser {
|
||||
&:hover {
|
||||
color: @wcfLinkColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.framed {
|
||||
> img, > canvas, > .icon {
|
||||
border-right-color: @wcfContentBackgroundColor;
|
||||
|
||||
border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius;
|
||||
&.notify {
|
||||
.notifyIcon {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.notify {
|
||||
> .userAvatar {
|
||||
> * {
|
||||
// TODO
|
||||
opacity: .4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timsChatMessageContainer {
|
||||
height: 320px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
display: none;
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.markEnabled {
|
||||
ul {
|
||||
.timsChatMessage {
|
||||
&.jsMarked {
|
||||
background-color: @wcfSelectedBackgroundColor;
|
||||
color: @wcfSelectedColor;
|
||||
}
|
||||
|
||||
> .innerMessageContainer {
|
||||
.markContainer {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
.timsChatMessage {
|
||||
min-height: 20px;
|
||||
clear: both;
|
||||
.transition(opacity, .2s);
|
||||
.timsChatMessageContainer {
|
||||
height: 300px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.unloaded {
|
||||
opacity: .5;
|
||||
}
|
||||
.timsChatMarkContainer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:nth-child(even) {
|
||||
> .innerMessageContainer.bubble .innerMessage {
|
||||
background-color: @wcfContainerAccentBackgroundColor;
|
||||
> ul {
|
||||
> .timsChatMessage {
|
||||
clear: both;
|
||||
|
||||
&:after {
|
||||
border-color: transparent @wcfContainerAccentBackgroundColor !important;
|
||||
}
|
||||
&.unloaded {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.messageIcon {
|
||||
float: left;
|
||||
padding: 8px 0 0 4px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
|
||||
> .innerMessageContainer {
|
||||
padding: 5px 20px 5px 5px;
|
||||
position: relative;
|
||||
|
||||
> div.avatarContainer {
|
||||
position: relative;
|
||||
> .timsChatMessageIcon {
|
||||
float: left;
|
||||
margin-left: 16px;
|
||||
|
||||
> .avatarExtra {
|
||||
box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.3);
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
bottom: -2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
margin-right: -16px;
|
||||
}
|
||||
|
||||
.innerMessage {
|
||||
margin-left: 46px;
|
||||
padding: 2px 5px 5px;
|
||||
> .timsChatInnerMessageContainer {
|
||||
position: relative;
|
||||
|
||||
time {
|
||||
float: right;
|
||||
}
|
||||
> .timsChatAvatarContainer {
|
||||
position: relative;
|
||||
float: left;
|
||||
margin-left: 16px;
|
||||
|
||||
.username {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
> .text {
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
> .timsChatAvatarExtraIcon {
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
right: -8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.bubble {
|
||||
> div.avatarContainer {
|
||||
margin-left: 0;
|
||||
}
|
||||
.timsChatInnerMessage {
|
||||
margin-left: 32 + @wcfGapMedium; // size of avatars + a small gap
|
||||
padding-right: @wcfGapSmall;
|
||||
|
||||
.innerMessage {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: @wcfContainerBorderColor;
|
||||
border-radius: @wcfContainerBorderRadius;
|
||||
background-color: @wcfContainerBackgroundColor;
|
||||
position: relative;
|
||||
|
||||
> 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;
|
||||
}
|
||||
.timsChatUsernameContainer {
|
||||
// sender username
|
||||
> span:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
&:before {
|
||||
.__bubbleArrow;
|
||||
}
|
||||
|
||||
&:after {
|
||||
.__bubbleArrow;
|
||||
border-color: transparent @wcfContainerBackgroundColor;
|
||||
left: -5px;
|
||||
top: 6px;
|
||||
border-width: 5px 5px 5px 0;
|
||||
time {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
.avatarContainer {
|
||||
float: right;
|
||||
&.bubble {
|
||||
> .timsChatAvatarContainer {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.innerMessage {
|
||||
margin-right: 46px;
|
||||
margin-left: 0px;
|
||||
.timsChatInnerMessage {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
.__bubbleArrow;
|
||||
left: auto;
|
||||
right: -6px;
|
||||
border-width: 6px 0 6px 6px;
|
||||
padding: @wcfGapSmall;
|
||||
border-radius: @wcfContainerBorderRadius;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: @wcfContainerBorderColor;
|
||||
|
||||
> .timsChatText {
|
||||
li {
|
||||
border-style: solid;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: @wcfContainerBorderColor;
|
||||
padding: (@wcfGapTiny - 1) 0 @wcfGapTiny;
|
||||
|
||||
&:last-child {
|
||||
border-style: none;
|
||||
padding: (@wcfGapTiny - 1) 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// :before and :after are used to create the little arrows on the “speech bubble containers”
|
||||
&:before, &:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
&:before{
|
||||
border-color: transparent @wcfContainerBorderColor;
|
||||
left: -@wcfGapSmall;
|
||||
top: @wcfGapSmall;
|
||||
border-width: @wcfGapSmall @wcfGapSmall @wcfGapSmall 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
.__bubbleArrow;
|
||||
border-color: transparent @wcfContainerBackgroundColor;
|
||||
left: auto;
|
||||
right: -5px;
|
||||
top: 6px;
|
||||
border-width: 5px 0 5px 5px;
|
||||
left: -@wcfGapSmall + 1;
|
||||
top: @wcfGapSmall + 1;
|
||||
border-width: (@wcfGapSmall - 1) (@wcfGapSmall - 1) (@wcfGapSmall - 1) 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
> .timsChatAvatarContainer {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.timsChatInnerMessage {
|
||||
margin-right: 32 + @wcfGapMedium;
|
||||
margin-left: 0;
|
||||
|
||||
&:before{
|
||||
border-color: transparent @wcfContainerBorderColor;
|
||||
left: auto;
|
||||
right: -@wcfGapSmall;
|
||||
top: @wcfGapSmall;
|
||||
border-width: @wcfGapSmall 0 @wcfGapSmall @wcfGapSmall;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-color: transparent @wcfContainerBackgroundColor;
|
||||
left: auto;
|
||||
right: -@wcfGapSmall + 1;
|
||||
top: @wcfGapSmall + 1;
|
||||
border-width: (@wcfGapSmall - 1) 0 (@wcfGapSmall - 1) (@wcfGapSmall - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .markContainer {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 6px;
|
||||
&:nth-child(even) {
|
||||
> .timsChatInnerMessageContainer {
|
||||
&.bubble {
|
||||
.timsChatInnerMessage {
|
||||
background-color: @wcfContainerAccentBackgroundColor;
|
||||
|
||||
&:after {
|
||||
border-color: transparent @wcfContainerAccentBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
> .timsChatInnerMessageContainer {
|
||||
margin-bottom: @wcfGapSmall;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.markEnabled {
|
||||
> ul {
|
||||
> .timsChatMessage {
|
||||
&.jsMarked {
|
||||
> .timsChatInnerMessageContainer {
|
||||
.timsChatInnerMessage {
|
||||
background-color: @wcfSelectedBackgroundColor;
|
||||
color: @wcfSelectedColor;
|
||||
}
|
||||
|
||||
&.bubble {
|
||||
.timsChatInnerMessage {
|
||||
&:after {
|
||||
border-color: transparent @wcfSelectedBackgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
.timsChatInnerMessage {
|
||||
&:after {
|
||||
border-color: transparent @wcfSelectedBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .timsChatInnerMessageContainer {
|
||||
.timsChatMarkContainer {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: -@wcfGapLarge;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#smilies {
|
||||
.marginTop();
|
||||
|
||||
// don't display the smiley box on low resolution devices as a button will be shown instead
|
||||
@media only screen and (max-width: 800px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&, &.invisible {
|
||||
-webkit-transition: opacity .2s ease-in-out;
|
||||
-moz-transition: opacity .2s ease-in-out;
|
||||
-ms-transition: opacity .2s ease-in-out;
|
||||
-o-transition: opacity .2s ease-in-out;
|
||||
transition: opacity .2s ease-in-out;
|
||||
}
|
||||
|
||||
&.invisible {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatOptions {
|
||||
float: right;
|
||||
|
||||
// styles related to the smiley button that replaces the smiley box on low resolution devices
|
||||
#timsChatSmileyPopupButton {
|
||||
display: none;
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
// fix option buttons on low resolution devices, it will become a dropup not a dropdown
|
||||
> nav.buttonGroupNavigation {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
margin-right: @wcfGapSmall;
|
||||
|
||||
> ul {
|
||||
right: 1px;
|
||||
top: auto;
|
||||
bottom: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear the float on the first element after the option container, maybe someone alters their templates and puts an element down there ;)
|
||||
+ * {
|
||||
clear: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
padding-top: 0px !important;
|
||||
|
||||
> div {
|
||||
height: 400px;
|
||||
overflow: auto !important;
|
||||
> .chatTabMenuContainer {
|
||||
padding: 14px 0 21px;
|
||||
> fieldset{
|
||||
padding-right: @wcfGapTiny;
|
||||
|
||||
> .chatSidebarMenu {
|
||||
background: @wcfContentBackgroundColor;
|
||||
margin: -14px 0 0;
|
||||
border-radius: 0px;
|
||||
> div {
|
||||
overflow-y: auto;
|
||||
|
||||
> ul {
|
||||
padding-right: @wcfGapSmall;
|
||||
}
|
||||
}
|
||||
|
||||
&#timsChatUserListContainer {
|
||||
> div {
|
||||
height: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
&#timsChatRoomListContainer {
|
||||
> div#timsChatRoomList {
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#sidebarContent {
|
||||
fieldset {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
nav {
|
||||
ul {
|
||||
> li {
|
||||
> a {
|
||||
padding: @wcfGapTiny @wcfGapMedium @wcfGapTiny @wcfGapLarge;
|
||||
height: 24px; // height of avatar image
|
||||
}
|
||||
|
||||
> a:before {
|
||||
display: inline-block;
|
||||
content: "";
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
> &.active {
|
||||
margin-top: @wcfGapSmall;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul:not(.dropdownMenu) {
|
||||
#timsChatUserList {
|
||||
> ul {
|
||||
> li {
|
||||
margin-top: @wcfGapSmall;
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatUserList {
|
||||
.timsChatUser {
|
||||
> a {
|
||||
background: @wcfContentBackgroundColor;
|
||||
|
||||
img {
|
||||
margin-right: @wcfGapSmall;
|
||||
&.you {
|
||||
a {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.away {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&.suspended a {
|
||||
text-decoration: line-through;
|
||||
a {
|
||||
img {
|
||||
margin-right: @wcfGapTiny;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -391,116 +457,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatRoomList {
|
||||
#timsChatCopyrightDialog {
|
||||
> div {
|
||||
> div {
|
||||
text-align: center;
|
||||
}
|
||||
background-repeat: no-repeat;
|
||||
background-position: right top;
|
||||
}
|
||||
}
|
||||
|
||||
#smilies {
|
||||
margin-top: @wcfGapMedium;
|
||||
|
||||
li {
|
||||
.transition(opacity, .2s);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
li {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatOptions {
|
||||
> ul {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
#timsChatCopyrightDialog > div {
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.notification {
|
||||
animation-duration: .2s;
|
||||
animation-name: timsChatNotify;
|
||||
animation-iteration-count: 5;
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: linear;
|
||||
border-color: @wcfInputHoverBorderColor;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
.timsChatMessage .text li > time, #smilies {
|
||||
display: none !important;
|
||||
}
|
||||
#fish {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
html.fullscreen {
|
||||
#top {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
#content {
|
||||
&,
|
||||
body,
|
||||
#tplChat #main,
|
||||
#tplChat #main > div,
|
||||
#tplChat #main > div > div,
|
||||
#tplChat #content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
display: -moz-box;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
|
||||
-webkit-box-orient: vertical;
|
||||
-moz-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-moz-box-direction: normal;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
|
||||
.timsChatMessageContainer {
|
||||
-webkit-box-flex: 1;
|
||||
-moz-box-flex: 1;
|
||||
-webkit-flex: 1 0 auto;
|
||||
-ms-flex: 1 0 auto;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
#timsChatOptions {
|
||||
margin-bottom: @wcfGapMedium;
|
||||
}
|
||||
|
||||
#tplChat {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
#pageHeader, #pageFooter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#main {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
|
||||
> div, .sidebar, #sidebarContainer {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
#top,
|
||||
#pageHeader,
|
||||
#pageFooter {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -36,10 +36,10 @@
|
||||
<dd>
|
||||
<ul>
|
||||
<li><a href="http://www.wbbaddons.de/user/2020-noone/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>-noone-</a></li>
|
||||
<li><a href="https://github.com/Gabbid" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Gabi</a></li>
|
||||
<li>Gabi</li>
|
||||
<li>Alexandra Glass</li>
|
||||
<li><a href="https://github.com/Leon-" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>Stefan Hahn</a></li>
|
||||
<li><a href="https://kittblog.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Matthias Kittsteiner</a></li>
|
||||
<li><a href="http://kittmedia.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Matthias Kittsteiner</a></li>
|
||||
<li><a href="http://www.wbbaddons.de" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Martin Schwendowius</a></li>
|
||||
<li><a href="http://www.cls-design.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Tom</a></li>
|
||||
</ul>
|
||||
|
@ -10,39 +10,44 @@
|
||||
(function ($, window) {
|
||||
$(function(){
|
||||
WCF.Language.addObject({
|
||||
'chat.general.query': '{lang}chat.general.query{/lang}',
|
||||
'chat.general.kick': '{lang}chat.general.kick{/lang}',
|
||||
'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': '{@"chat.error.onMessageLoad"|language|encodeJS}',
|
||||
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
||||
'chat.general.privateChannelTopic': '{lang}chat.general.privateChannelTopic{/lang}',
|
||||
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
||||
'chat.general.query': '{lang}chat.general.query{/lang}',
|
||||
'chat.general.whisper': '{lang}chat.general.whisper{/lang}',
|
||||
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
||||
'chat.error.join': '{lang}chat.error.join{/lang}',
|
||||
'chat.error.onMessageLoad': '{@"chat.error.onMessageLoad"|language|encodeJS}',
|
||||
'chat.error.reload': '{lang}chat.error.reload{/lang}',
|
||||
'chat.message.{$messageTypes[TYPE_ATTACHMENT]}': '{lang}chat.message.{$messageTypes[TYPE_ATTACHMENT]}{/lang}',
|
||||
'wcf.attachment.insert': '{lang}wcf.attachment.insert{/lang}',
|
||||
'wcf.attachment.delete.sure': '{lang}wcf.attachment.delete.sure{/lang}',
|
||||
'wcf.attachment.upload.error.invalidExtension': '{lang}wcf.attachment.upload.error.invalidExtension{/lang}',
|
||||
'wcf.attachment.upload.error.tooLarge': '{lang}wcf.attachment.upload.error.tooLarge{/lang}',
|
||||
'wcf.attachment.upload.error.reachedLimit': '{lang}wcf.attachment.upload.error.reachedLimit{/lang}',
|
||||
'wcf.attachment.upload.error.reachedRemainingLimit': '{lang}wcf.attachment.upload.error.reachedRemainingLimit{/lang}',
|
||||
'wcf.attachment.upload.error.uploadFailed': '{lang}wcf.attachment.upload.error.uploadFailed{/lang}',
|
||||
'wcf.global.button.upload': '{lang}wcf.global.button.upload{/lang}',
|
||||
'wcf.attachment.insert': '{lang}wcf.attachment.insert{/lang}',
|
||||
'wcf.attachment.delete.sure': '{lang}wcf.attachment.delete.sure{/lang}',
|
||||
'chat.message.{$messageTypes[TYPE_ATTACHMENT]}': '{lang}chat.message.{$messageTypes[TYPE_ATTACHMENT]}{/lang}'
|
||||
'wcf.global.button.upload': '{lang}wcf.global.button.upload{/lang}'
|
||||
});
|
||||
|
||||
// Boot the chat
|
||||
{if MODULE_SMILEY}WCF.TabMenu.init();{/if}
|
||||
{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}
|
||||
new be.bastelstu.Chat.Attachment();
|
||||
new be.bastelstu.Chat.Action.Delete('wcf\\data\\attachment\\AttachmentAction', '#timsChatUploadDropdownMenu > li');
|
||||
{/if}
|
||||
new WCF.Message.Smilies();
|
||||
|
||||
WCF.TabMenu.init();
|
||||
|
||||
{if MODULE_SMILEY}
|
||||
new WCF.Message.Smilies();
|
||||
{/if}
|
||||
|
||||
{capture assign='messageTemplate'}{include application='chat' file='message'}{/capture}
|
||||
{capture assign='userTemplate'}{include application='chat' file='userListUser'}{/capture}
|
||||
{capture assign='userMenuTemplate'}{include application='chat' file='userListUserMenu'}{/capture}
|
||||
|
||||
var config = {
|
||||
reloadTime: {@CHAT_RELOADTIME},
|
||||
@ -58,12 +63,13 @@
|
||||
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}')
|
||||
new WCF.Template('{@$userTemplate|encodeJS}'),
|
||||
new WCF.Template('{@$userMenuTemplate|encodeJS}')
|
||||
);
|
||||
|
||||
{event name='afterInit'}
|
||||
|
||||
$('#timsChatCopyright').click(function (event) {
|
||||
$('#timsChatCopyright a').click(function (event) {
|
||||
event.preventDefault();
|
||||
if (!$.wcfIsset('timsChatCopyrightDialog')) $('<div id="timsChatCopyrightDialog"></div>').appendTo('body');
|
||||
$('#timsChatCopyrightDialog').load('{link application="chat" controller="Copyright"}{/link}').wcfDialog({
|
||||
@ -80,78 +86,118 @@
|
||||
{capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture}
|
||||
{include file='header' sandbox=false sidebarOrientation='right'}
|
||||
|
||||
<div id="timsChatTopic" class="marginTop 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 class="clearfix">
|
||||
<div id="timsChatTopic" class="container containerPadding marginTop{if $room->topic|language === ''} empty{/if}">
|
||||
<span id="timsChatTopicCloser" class="icon icon16 icon-remove jsTooltip" title="{lang}chat.general.closeTopic{/lang}"></span>
|
||||
<span class="topic">{$room->topic|language}</span>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<form id="timsChatForm" action="{link application='chat' controller='Chat' action='Send'}{/link}" method="post">
|
||||
<fieldset>
|
||||
<dl class="wide" id="timsChatInputContainer">
|
||||
<dt>
|
||||
{lang}chat.general.message{/lang}
|
||||
</dt>
|
||||
<dd>
|
||||
<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>
|
||||
</fieldset>
|
||||
<button type="submit" class="invisible" accesskey="s"></button>
|
||||
</form>
|
||||
|
||||
{if MODULE_SMILEY && $smileyCategories|count}
|
||||
{include file='messageFormSmilies' wysiwygSelector=''}
|
||||
{/if}
|
||||
|
||||
<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>{*
|
||||
|
||||
*}<li><a id="timsChatFullscreen" accesskey="f" class="button timsChatToggle jsTooltip" title="{lang}chat.general.fullscreen{/lang}" data-status="0"><span class="icon icon16 icon-fullscreen"></span><span class="invisible">{lang}chat.general.fullscreen{/lang}</span></a></li>{*
|
||||
|
||||
*}<li><a id="timsChatNotify" accesskey="n" class="button timsChatToggle jsTooltip" title="{lang}chat.general.notify{/lang}" data-status="0"><span class="icon icon16 icon-bell-alt"></span><span class="invisible">{lang}chat.general.notify{/lang}</span></a></li>{*
|
||||
|
||||
*}<li{if !MODULE_SMILEY || !$smileyCategories|count} style="display: none;"{/if}><a id="timsChatSmilies" accesskey="e" class="button{if ENABLE_SMILIES_DEFAULT_VALUE} active{/if} timsChatToggle jsTooltip" title="{lang}chat.general.smilies{/lang}" data-status="{@ENABLE_SMILIES_DEFAULT_VALUE}"><span class="icon icon16 icon-smile"></span><span class="invisible">{lang}chat.general.smilies{/lang}</span></a></li>{*
|
||||
|
||||
*}{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}{*
|
||||
*}<li id="timsChatUploadContainer" class="dropdown" data-max-size="{$attachmentHandler->getMaxSize()}">
|
||||
<a id="timsChatUpload" class="dropdownToggle button jsTooltip" title="{lang}wcf.attachment.attachments{/lang}" data-toggle="timsChatUploadContainer">
|
||||
<span class="icon icon16 icon-paper-clip"></span>
|
||||
<span class="invisible">{lang}wcf.attachment.attachments{/lang}</span>
|
||||
</a>
|
||||
<ul id="timsChatUploadDropdownMenu" class="dropdownMenu">
|
||||
<li class="uploadButton" style="margin-top: 0;">
|
||||
<span><label for="timsChatUploadInput">{lang}wcf.global.button.upload{/lang}</label></span>
|
||||
<div id="timsChatMessageTabMenu" class="tabMenuContainer singleTab" data-active="timsChatMessageContainer0">
|
||||
<nav class="tabMenu">
|
||||
<ul>
|
||||
<li>
|
||||
<a id="timsChatMessageTabMenuAnchor0" href="{$__wcf->getAnchor('timsChatMessageContainer0')}" class="timsChatMessageTabMenuAnchor" data-user-id="0">
|
||||
<span class="icon icon16 icon-warning-sign notifyIcon"></span>{*
|
||||
*}<span class="userAvatar framed">
|
||||
<span class="icon icon16 icon-group"></span>
|
||||
</span>{*
|
||||
*}<span>{$room}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>{/if}{*
|
||||
</nav>
|
||||
|
||||
*}<li><a id="timsChatClear" class="button jsTooltip" title="{lang}chat.general.clear{/lang}"><span class="icon icon16 icon-remove"></span><span class="invisible">{lang}chat.general.clear{/lang}</span></a></li>{*
|
||||
<div id="timsChatMessageContainer0" class="tabMenuContent timsChatMessageContainer container containerPadding active" data-user-id="0">
|
||||
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
||||
<ul></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
*}<li><a id="timsChatMark" class="button timsChatToggle jsTooltip" title="{lang}chat.general.mark{/lang}" data-status="0"><span class="icon icon16 icon-check"></span><span class="invisible">{lang}chat.general.mark{/lang}</span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<form id="timsChatForm" action="{link application='chat' controller='Chat' action='Send'}{/link}" method="post">
|
||||
<fieldset>
|
||||
<dl class="wide" id="timsChatInputContainer">
|
||||
<dt>
|
||||
{lang}chat.general.message{/lang}
|
||||
</dt>
|
||||
<dd>
|
||||
<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>
|
||||
</fieldset>
|
||||
<button type="submit" class="marginTop invisible" accesskey="s">{lang}wcf.global.button.submit{/lang}</button>
|
||||
</form>
|
||||
|
||||
{if MODULE_SMILEY && $smileyCategories|count}
|
||||
{include file='messageFormSmilies' wysiwygSelector=''}
|
||||
{/if}
|
||||
|
||||
<div id="timsChatOptions" class="marginTop">
|
||||
<span id="timsChatSmileyPopupButton" class="button smallButtons">
|
||||
<span class="icon icon16 icon-smile"></span>
|
||||
<span>{lang}chat.general.smilies{/lang}</span>
|
||||
</span>
|
||||
|
||||
<nav class="jsMobileNavigation buttonGroupNavigation">
|
||||
<ul class="buttonGroup">
|
||||
<li>
|
||||
<a id="timsChatAutoscroll" accesskey="d" class="button active timsChatToggle jsTooltip" title="{lang}chat.general.scroll{/lang}" data-status="1">
|
||||
<span class="icon icon16 icon-arrow-down"></span>
|
||||
<span class="invisible">{lang}chat.general.scroll{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatFullscreen" accesskey="f" class="button timsChatToggle jsTooltip" title="{lang}chat.general.fullscreen{/lang}" data-status="0">
|
||||
<span class="icon icon16 icon-fullscreen"></span>
|
||||
<span class="invisible">{lang}chat.general.fullscreen{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatNotify" accesskey="n" class="button timsChatToggle jsTooltip" title="{lang}chat.general.notify{/lang}" data-status="0">
|
||||
<span class="icon icon16 icon-bell-alt"></span>
|
||||
<span class="invisible">{lang}chat.general.notify{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{if MODULE_SMILEY && $smileyCategories|count}
|
||||
<li>
|
||||
<a id="timsChatSmilies" accesskey="e" class="button{if ENABLE_SMILIES_DEFAULT_VALUE} active{/if} timsChatToggle jsTooltip" title="{lang}chat.general.smilies{/lang}" data-status="{@ENABLE_SMILIES_DEFAULT_VALUE}">
|
||||
<span class="icon icon16 icon-smile"></span>
|
||||
<span class="invisible">{lang}chat.general.smilies{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}
|
||||
<li id="timsChatUploadContainer" class="dropdown" data-max-size="{$attachmentHandler->getMaxSize()}">
|
||||
<a id="timsChatUpload" class="dropdownToggle button jsTooltip" title="{lang}wcf.attachment.attachments{/lang}" data-toggle="timsChatUploadContainer">
|
||||
<span class="icon icon16 icon-paper-clip"></span>
|
||||
<span class="invisible">{lang}wcf.attachment.attachments{/lang}</span>
|
||||
</a>
|
||||
<ul id="timsChatUploadDropdownMenu" class="dropdownMenu">
|
||||
<li class="uploadButton" style="margin-top: 0;">
|
||||
<span><label for="timsChatUploadInput" class="pointer">{lang}wcf.global.button.upload{/lang}</label></span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<li>
|
||||
<a id="timsChatClear" class="button jsTooltip" title="{lang}chat.general.clear{/lang}">
|
||||
<span class="icon icon16 icon-remove"></span>
|
||||
<span class="invisible">{lang}chat.general.clear{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="timsChatMark" class="button timsChatToggle jsTooltip" title="{lang}chat.general.mark{/lang}" data-status="0">
|
||||
<span class="icon icon16 icon-check"></span>
|
||||
<span class="invisible">{lang}chat.general.mark{/lang}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include file='footer' sandbox=false}
|
||||
</body>
|
||||
|
@ -1,12 +1,12 @@
|
||||
{literal}
|
||||
{if $message.type == $messageTypes.LEAVE || $message.type == $messageTypes.JOIN}
|
||||
<div class="messageIcon">
|
||||
<span class="icon icon16 icon-{if $message.type == $messageTypes.LEAVE}signout{elseif $message.type == $messageTypes.JOIN}signin{/if}"></span>
|
||||
{if $message.type == $messageTypes.JOIN || $message.type == $messageTypes.LEAVE}
|
||||
<div class="timsChatMessageIcon">
|
||||
<span class="icon icon16 icon-{if $message.type == $messageTypes.JOIN}signin{else}signout{/if}"></span>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="innerMessageContainer{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.INFORMATION || $message.type == $messageTypes.ATTACHMENT} bubble{/if}{if $message.type == $messageTypes.WHISPER && $message.sender != $__wcf.User.userID} right{/if}">
|
||||
<div class="avatarContainer">
|
||||
<div class="userAvatar{if $message.type != $messageTypes.INFORMATION} framed{/if}">
|
||||
<div class="timsChatInnerMessageContainer{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.INFORMATION || $message.type == $messageTypes.ATTACHMENT} bubble{/if}{if $message.type == $messageTypes.WHISPER && $message.sender != $__wcf.User.userID} right{/if}">
|
||||
<div class="timsChatAvatarContainer">
|
||||
<div class="userAvatar framed">
|
||||
{if $message.type != $messageTypes.INFORMATION}
|
||||
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.ATTACHMENT}
|
||||
{@$message.avatar[32]}
|
||||
@ -18,46 +18,38 @@
|
||||
{/if}
|
||||
</div>
|
||||
{if $message.type == $messageTypes.ATTACHMENT}
|
||||
<small class="framed avatarExtra">
|
||||
<small class="framed timsChatAvatarExtraIcon">
|
||||
<span class="icon icon16 icon-paperclip"></span>
|
||||
</small>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="innerMessage">
|
||||
<span class="username">
|
||||
{if ($message.type == $messageTypes.WHISPER && $message.sender == WCF.User.userID) || $message.type != $messageTypes.WHISPER}
|
||||
<div class="timsChatInnerMessage">
|
||||
<span class="timsChatUsernameContainer">
|
||||
{@$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 $message.type == $messageTypes.WHISPER}
|
||||
<span class="icon icon16 icon-double-angle-right jsTooltip" title="{/literal}{lang}chat.general.whisper{/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>
|
||||
<span class="reciever">{$message.additionalData.receiverUsername}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
<time>{@$message.formattedTime}</time>
|
||||
|
||||
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.ATTACHMENT}
|
||||
{if $message.type == $messageTypes.ATTACHMENT}<span>{lang}chat.message.{$messageTypes.ATTACHMENT}{/lang}</span>{/if}
|
||||
<ul class="text">
|
||||
<ul class="timsChatText">
|
||||
<li>
|
||||
{if $message.isFollowUp} <time>{@$message.formattedTime}</time>{/if}
|
||||
{@$message.formattedMessage}
|
||||
</li>
|
||||
</ul>
|
||||
{elseif $message.type == $messageTypes.INFORMATION}
|
||||
<div class="text">{@$message.formattedMessage}</div>
|
||||
<div class="timsChatText">{@$message.formattedMessage}</div>
|
||||
{else}
|
||||
<span class="text">{@$message.formattedMessage}</span>
|
||||
<span class="timsChatText">{@$message.formattedMessage}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<span class="markContainer">
|
||||
<span class="timsChatMarkContainer">
|
||||
<input type="checkbox" value="{@$message.messageID}" />
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,29 +1,19 @@
|
||||
<div class="tabMenuContainer chatTabMenuContainer containerPadding">
|
||||
<nav class="menu chatSidebarMenu">
|
||||
<ul>
|
||||
<li id="toggleUsers" class="ui-state-active"><a href="{@$__wcf->getAnchor('timsChatUserList')}" title="{lang}chat.general.users{/lang}">{lang}chat.general.users{/lang} <span class="badge">0</span></a></li>
|
||||
<li id="toggleRooms"><a href="{@$__wcf->getAnchor('timsChatRoomList')}" title="{lang}chat.general.rooms{/lang}">{lang}chat.general.rooms{/lang} <span class="badge">0</span></a></li>
|
||||
<fieldset id="timsChatUserListContainer">
|
||||
<legend>{lang}chat.general.users{/lang}</legend>
|
||||
<div id="timsChatUserList">
|
||||
<ul class="sidebarNestedCategoryList">
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset id="timsChatRoomListContainer">
|
||||
<legend>{lang}chat.general.rooms{/lang}</legend>
|
||||
<div id="timsChatRoomList">
|
||||
<ul class="sidebarNestedCategoryList">
|
||||
|
||||
<section id="sidebarContent" class="tabMenuContent">
|
||||
<fieldset>
|
||||
<nav id="timsChatUserList">
|
||||
<ul>
|
||||
</ul>
|
||||
</nav>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<nav id="timsChatRoomList" style="display: none;">
|
||||
<div>
|
||||
<ul>
|
||||
</ul>
|
||||
<div class="marginTop">
|
||||
<button type="button">{lang}chat.general.forceRefresh{/lang}</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</fieldset>
|
||||
</section>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="marginTop">
|
||||
<a id="timsChatRoomListReloadButton" class="button small jsOnly">{lang}chat.general.forceRefresh{/lang}</a>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
@ -1 +1 @@
|
||||
{literal}<a{if $userID != $__wcf.User.userID} class="dropdownToggle"{/if} data-user-id="{$userID.toString()}">{@$avatar['24']}{$username}</a>{/literal}
|
||||
{literal}<a{if $userID != $__wcf.User.userID} class="dropdownToggle"{/if} data-user-id="{$userID.toString()}"><span class="framed">{@$avatar['24']}</span>{$username}</a>{/literal}
|
||||
|
8
template/userListUserMenu.tpl
Normal file
8
template/userListUserMenu.tpl
Normal file
@ -0,0 +1,8 @@
|
||||
{literal}
|
||||
<ul data-user-id="{$userID}">
|
||||
<li><a class="jsTimsChatUserMenuWhisper">{lang}chat.general.whisper{/lang}</a></li>
|
||||
<li><a class="jsTimsChatUserMenuQuery">{lang}chat.general.query{/lang}</a></li>
|
||||
<li><a class="jsTimsChatUserMenuBan">{lang}chat.general.ban{/lang}</a></li>
|
||||
<li><a href="{$link}" class="userLink" data-user-id="{$userID}">{lang}chat.general.profile{/lang}</a></li>
|
||||
</ul>
|
||||
{/literal}
|
Loading…
Reference in New Issue
Block a user