From c690927d486402904d19195abdb4b50118208970 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Fri, 12 Jul 2013 16:49:40 +0200 Subject: [PATCH 1/6] Add graphical interface for private channels. --- file/js/be.bastelstu.Chat.litcoffee | 78 +++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/file/js/be.bastelstu.Chat.litcoffee b/file/js/be.bastelstu.Chat.litcoffee index 5776b7a..06a9399 100644 --- a/file/js/be.bastelstu.Chat.litcoffee +++ b/file/js/be.bastelstu.Chat.litcoffee @@ -33,13 +33,17 @@ exposed by a function if necessary. newMessageCount = 0 scrollUpNotifications = off chatSession = Date.now() - + userList = + current: {} + allTime: {} + + errorVisible = false inputErrorHidingTimer = null lastMessage = null openChannel = 0 - + remainingFailures = 3 events = @@ -113,6 +117,11 @@ Insert the appropriate smiley code into the input when a smiley is clicked. $('#smilies').on 'click', 'img', -> 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. @@ -125,7 +134,7 @@ and afterwards sent to the server by an AJAX request. return false if text.length is 0 unless openChannel is 0 - text = "/whisper #{$("#timsChatMessageContainer#{openChannel}").data 'username'}, #{text}" + text = "/whisper #{userList.allTime[openChannel].username}, #{text}" # 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 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 @@ -488,9 +500,12 @@ 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. @@ -697,26 +712,71 @@ Joins a room. Open private channel openPrivateChannel = (userID) -> + userID = parseInt userID + + console.log "Opening private channel #{userID}" + unless $.wcfIsset "timsChatMessageContainer#{userID}" - return unless $.wcfIsset "timsChatUser#{userID}" + return unless userList.allTime[userID]? - div = $('
') + div = $ '
' div.attr 'id', "timsChatMessageContainer#{userID}" div.addClass 'timsChatMessageContainer' div.addClass 'marginTop' div.addClass 'container' - div.data 'username', $("#timsChatUser#{userID}").data 'username' div.wrapInner '
    ' $('#timsChatMessageContainer0').after div + + channels = $ '#privateChannelsMenu li' + channels.removeClass 'active' + channels.each (key, channel) -> + channel = $ channel; + privateChannelID = channel.data 'privateChannelID' + + if privateChannelID isnt 0 + channel.find('.userAvatar > *').replaceWith userList.allTime[privateChannelID].avatar[16] + else + channel.find('.icon').removeClass('icon32').addClass 'icon16' + + if userID isnt 0 + if $.wcfIsset "privateChannel#{userID}" + $("#privateChannel#{userID} > .userAvatar > img").replaceWith userList.allTime[userID].avatar[32] + else + li = $ '
  • ' + li.attr 'id', "privateChannel#{userID}" + li.data 'privateChannelID', userID + li.addClass 'privateChannel' + li.addClass 'active' + li.append userList.allTime[userID].avatar[32] + + span = $ '' + span.addClass 'jsTooltip' + span.attr 'title', userList.allTime[userID].username + + li.wrapInner span + $('#privateChannelsMenu ul').append li + + do WCF.DOMNodeInsertedHandler.execute + + $('#privateChannelsMenu').addClass 'shown' + else + $("#privateChannel0 > .userAvatar > .icon").removeClass('icon16').addClass 'icon32' $('.timsChatMessageContainer').removeClass 'active' $("#timsChatMessageContainer#{userID}").addClass 'active' + $("#privateChannel#{userID}").addClass 'active' openChannel = userID Close private channel 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 Bind the given callback to the given event. From 3bdbc2159bc938c0eb73c5928ea6bc2dc5e6317e Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Fri, 12 Jul 2013 17:15:13 +0200 Subject: [PATCH 2/6] Add forgotten files Maybe I was asleep ... I don't know. --- file/style/be.bastelstu.wcf.chat.less | 65 +++++++++++++++++++++++++++ template/chat.tpl | 13 +++--- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/file/style/be.bastelstu.wcf.chat.less b/file/style/be.bastelstu.wcf.chat.less index 421dc30..68c9462 100644 --- a/file/style/be.bastelstu.wcf.chat.less +++ b/file/style/be.bastelstu.wcf.chat.less @@ -58,6 +58,71 @@ } } + #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.framed { + > .icon { + background-color: @wcfContentBackgroundColor; + border: 1px solid @wcfContainerBorderColor; + padding: 1px; + } + } + + &.active { + > .userAvatar.framed { + > img, > canvas, > .icon { + border-right-color: @wcfContentBackgroundColor; + + border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius; + } + } + } + } + } + } + .timsChatMessageContainer { height: 320px; overflow-y: scroll; diff --git a/template/chat.tpl b/template/chat.tpl index c607415..e872940 100644 --- a/template/chat.tpl +++ b/template/chat.tpl @@ -53,12 +53,6 @@ title: ' {if SHOW_VERSION_NUMBER} {PACKAGE_VERSION}{/if}' }); }); - - $('#chatLogLink').click(function (event) { - event.preventDefault(); - - be.bastelstu.Chat.Log.loadOverlay(); - }); }); })(jQuery, this); //]]> @@ -67,7 +61,6 @@ {capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture} - {capture assign='headerNavigation'}{include application='chat' file='navigationInclude'}{/capture} {include file='header' sandbox=false sidebarOrientation='right'}
    @@ -75,6 +68,12 @@ {$room->topic|language}
    +
    +
      +
    • +
    +
    +
      From a330127c0bab270c609c85d06b763b1eb73e0437 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Fri, 12 Jul 2013 17:20:06 +0200 Subject: [PATCH 3/6] Readd accidentally deleted template code This shouldn't be deleted in this branch. --- template/chat.tpl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/template/chat.tpl b/template/chat.tpl index e872940..423a9b7 100644 --- a/template/chat.tpl +++ b/template/chat.tpl @@ -53,6 +53,12 @@ title: ' {if SHOW_VERSION_NUMBER} {PACKAGE_VERSION}{/if}' }); }); + + $('#chatLogLink').click(function (event) { + event.preventDefault(); + + be.bastelstu.Chat.Log.loadOverlay(); + }); }); })(jQuery, this); //]]> @@ -61,6 +67,7 @@ {capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture} + {capture assign='headerNavigation'}{include application='chat' file='navigationInclude'}{/capture} {include file='header' sandbox=false sidebarOrientation='right'}
      From 3580ebfd5cdee1d4fb00de66fb0df1b1a0da7376 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Fri, 12 Jul 2013 20:52:54 +0200 Subject: [PATCH 4/6] Simplify code a bit --- file/js/be.bastelstu.Chat.litcoffee | 42 +++++++++------------------ file/style/be.bastelstu.wcf.chat.less | 40 ++++++++++++++++++------- template/chat.tpl | 9 +++++- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/file/js/be.bastelstu.Chat.litcoffee b/file/js/be.bastelstu.Chat.litcoffee index 06a9399..3ab3f6d 100644 --- a/file/js/be.bastelstu.Chat.litcoffee +++ b/file/js/be.bastelstu.Chat.litcoffee @@ -710,12 +710,12 @@ Joins a room. 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]? @@ -726,42 +726,28 @@ Open private channel div.addClass 'container' div.wrapInner '
        ' $('#timsChatMessageContainer0').after div - - channels = $ '#privateChannelsMenu li' - channels.removeClass 'active' - channels.each (key, channel) -> - channel = $ channel; - privateChannelID = channel.data 'privateChannelID' - - if privateChannelID isnt 0 - channel.find('.userAvatar > *').replaceWith userList.allTime[privateChannelID].avatar[16] - else - channel.find('.icon').removeClass('icon32').addClass 'icon16' - + + $('.privateChannel').removeClass 'active' if userID isnt 0 - if $.wcfIsset "privateChannel#{userID}" - $("#privateChannel#{userID} > .userAvatar > img").replaceWith userList.allTime[userID].avatar[32] - else + unless $.wcfIsset "privateChannel#{userID}" li = $ '
      • ' li.attr 'id', "privateChannel#{userID}" li.data 'privateChannelID', userID li.addClass 'privateChannel' - li.addClass 'active' - li.append userList.allTime[userID].avatar[32] - + span = $ '' span.addClass 'jsTooltip' span.attr 'title', userList.allTime[userID].username - li.wrapInner span + li.append $(userList.allTime[userID].avatar[16]).wrap(span).parent().addClass 'small' + li.append $(userList.allTime[userID].avatar[32]).wrap(span).parent().addClass 'large' + $('#privateChannelsMenu ul').append li - + do WCF.DOMNodeInsertedHandler.execute - + $('#privateChannelsMenu').addClass 'shown' - else - $("#privateChannel0 > .userAvatar > .icon").removeClass('icon16').addClass 'icon32' - + $('.timsChatMessageContainer').removeClass 'active' $("#timsChatMessageContainer#{userID}").addClass 'active' $("#privateChannel#{userID}").addClass 'active' @@ -773,7 +759,7 @@ Close private channel unless userID is 0 do $("#privateChannel#{userID}").remove do $("#timsChatMessageContainer#{userID}").remove - + if $('#privateChannelsMenu li').length <= 1 $('#privateChannelsMenu').removeClass 'shown' @@ -809,7 +795,7 @@ And finally export the public methods and variables. listener: add: addListener remove: removeListener - + window.be ?= {} be.bastelstu ?= {} window.be.bastelstu.Chat = Chat diff --git a/file/style/be.bastelstu.wcf.chat.less b/file/style/be.bastelstu.wcf.chat.less index 68c9462..167d87e 100644 --- a/file/style/be.bastelstu.wcf.chat.less +++ b/file/style/be.bastelstu.wcf.chat.less @@ -102,20 +102,40 @@ cursor: pointer; } - > .userAvatar.framed { - > .icon { - background-color: @wcfContentBackgroundColor; - border: 1px solid @wcfContainerBorderColor; - padding: 1px; + > .userAvatar { + &.large { + display: none; + } + + &.small { + display: block; + } + + &.framed { + > .icon { + background-color: @wcfContentBackgroundColor; + border: 1px solid @wcfContainerBorderColor; + padding: 1px; + } } } &.active { - > .userAvatar.framed { - > img, > canvas, > .icon { - border-right-color: @wcfContentBackgroundColor; - - border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius; + > .userAvatar { + &.large { + display: block; + } + + &.small { + display: none; + } + + &.framed { + > img, > canvas, > .icon { + border-right-color: @wcfContentBackgroundColor; + + border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius; + } } } } diff --git a/template/chat.tpl b/template/chat.tpl index 423a9b7..9efa291 100644 --- a/template/chat.tpl +++ b/template/chat.tpl @@ -77,7 +77,14 @@
          -
        • +
        • + + + + + + +
        From de96de5941588d6abdfe476e9729a3a824cd4add Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Fri, 12 Jul 2013 21:29:17 +0200 Subject: [PATCH 5/6] Fix tooltip positioning --- file/js/be.bastelstu.Chat.litcoffee | 15 +++++++++++---- template/chat.tpl | 8 ++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/file/js/be.bastelstu.Chat.litcoffee b/file/js/be.bastelstu.Chat.litcoffee index 3ab3f6d..701d5bb 100644 --- a/file/js/be.bastelstu.Chat.litcoffee +++ b/file/js/be.bastelstu.Chat.litcoffee @@ -736,11 +736,18 @@ Open private channel li.addClass 'privateChannel' span = $ '' - span.addClass 'jsTooltip' - span.attr 'title', userList.allTime[userID].username - li.append $(userList.allTime[userID].avatar[16]).wrap(span).parent().addClass 'small' - li.append $(userList.allTime[userID].avatar[32]).wrap(span).parent().addClass 'large' + 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 diff --git a/template/chat.tpl b/template/chat.tpl index 9efa291..d7194f3 100644 --- a/template/chat.tpl +++ b/template/chat.tpl @@ -78,11 +78,11 @@
        • - - + + - - + +
        From a0cf213e486705dfa08de3ccd27b5df3a5991056 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Wed, 24 Jul 2013 12:55:47 +0200 Subject: [PATCH 6/6] Closing of private channels is now possible, add notifications to private channel tab menu (style is just a placeholder right now) --- file/js/be.bastelstu.Chat.litcoffee | 54 ++++++++++++++++++++------- file/style/be.bastelstu.wcf.chat.less | 9 +++++ language/de.xml | 4 ++ template/chat.tpl | 7 +++- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/file/js/be.bastelstu.Chat.litcoffee b/file/js/be.bastelstu.Chat.litcoffee index 701d5bb..0287111 100644 --- a/file/js/be.bastelstu.Chat.litcoffee +++ b/file/js/be.bastelstu.Chat.litcoffee @@ -36,7 +36,7 @@ exposed by a function if necessary. userList = current: {} allTime: {} - + currentRoom = {} errorVisible = false inputErrorHidingTimer = null @@ -279,8 +279,11 @@ Toggle checkboxes. Hide topic container. $('.jsTopicCloser').on 'click', -> - $('#timsChatTopic').addClass 'hidden' - + 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) -> @@ -450,10 +453,10 @@ Insert the given messages into the chat stream. $('.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 - message.isInPrivateChannel = (String(message.type) is v.config.messageTypes.WHISPER) and ($.wcfIsset("timsChatMessageContainer#{message.receiver}") or $.wcfIsset("timsChatMessageContainer#{message.sender}")) - 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 @@ -598,6 +601,17 @@ Send out notifications for the given `message`. The number of unread messages wi if scrollUpNotifications $('.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 document.title = v.titleTemplate.fetch @@ -693,17 +707,19 @@ Joins a room. loading = false $('#timsChatTopic').removeClass 'hidden' + currentRoom = data.returnValues + currentRoom.roomID = roomID - $('#timsChatTopic > .topic').text data.returnValues.topic - if data.returnValues.topic.trim() is '' + $('#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 + document.title = v.titleTemplate.fetch currentRoom + handleMessages currentRoom.messages do getMessages do refreshRoomList failure: -> @@ -721,6 +737,7 @@ Open private channel div = $ '
        ' div.attr 'id', "timsChatMessageContainer#{userID}" + div.data 'userID', userID div.addClass 'timsChatMessageContainer' div.addClass 'marginTop' div.addClass 'container' @@ -729,6 +746,10 @@ Open private channel $('.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.attr 'id', "privateChannel#{userID}" @@ -751,13 +772,20 @@ Open private channel $('#privateChannelsMenu ul').append li - do WCF.DOMNodeInsertedHandler.execute - $('#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' + $("#privateChannel#{userID}").addClass('active').removeClass 'notify' openChannel = userID Close private channel diff --git a/file/style/be.bastelstu.wcf.chat.less b/file/style/be.bastelstu.wcf.chat.less index 167d87e..aafc0cb 100644 --- a/file/style/be.bastelstu.wcf.chat.less +++ b/file/style/be.bastelstu.wcf.chat.less @@ -139,6 +139,15 @@ } } } + + &.notify { + > .userAvatar { + > * { + // TODO + opacity: .4; + } + } + } } } } diff --git a/language/de.xml b/language/de.xml index df1ac9a..c46fc3f 100644 --- a/language/de.xml +++ b/language/de.xml @@ -137,6 +137,10 @@ type}{/lang} ({if $room}{$room}{else}{lang}chat.room.global{/lang}{/if})]]> + + + + diff --git a/template/chat.tpl b/template/chat.tpl index d7194f3..73f015c 100644 --- a/template/chat.tpl +++ b/template/chat.tpl @@ -15,6 +15,9 @@ '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}', @@ -71,7 +74,7 @@ {include file='header' sandbox=false sidebarOrientation='right'}
        - + {$room->topic|language}
        @@ -88,7 +91,7 @@
      -
      +