diff --git a/client/stylesheets/base.less b/client/stylesheets/base.less index 0697d859c9a4..992a678cb8fc 100644 --- a/client/stylesheets/base.less +++ b/client/stylesheets/base.less @@ -2455,149 +2455,150 @@ a.github-fork { border-radius: 4px; } } - .message { - font-size: 14px; - padding-left: 50px; - position: relative; - line-height: 20px; - margin: 12px 20px 5px; - margin-top: 12px; - min-height: 40px; - &:nth-child(1) { - margin-top: 0; - } - &.new-day { - margin-top: 60px; - } - &.new-day { - &:before { - content: attr(data-date); - display: block; - position: absolute; - top: -30px; - left: 0; - font-size: 12px; - font-weight: 600; - text-align: center; - .calc(left, - ~"50% - 70px"); - color: @secondary-font-color; - z-index: 10; - padding: 0 10px; - background-color: #FFF; - min-width: 140px; - } - &:after { - content: " "; - display: block; - position: absolute; - top: -20px; - left: 0; - width: 100%; - border-top: 1px solid #ddd; - } - } - .edit-message { - display: none; - cursor: pointer; - } - &.own:hover:not(.system) .edit-message { - display: inline-block; +} + +.message { + font-size: 14px; + padding-left: 50px; + position: relative; + line-height: 20px; + margin: 12px 20px 5px; + margin-top: 12px; + min-height: 40px; + &:nth-child(1) { + margin-top: 0; + } + &.new-day { + margin-top: 60px; + } + &.new-day { + &:before { + content: attr(data-date); + display: block; + position: absolute; + top: -30px; + left: 0; + font-size: 12px; + font-weight: 600; + text-align: center; + .calc(left, + ~"50% - 70px"); + color: @secondary-font-color; + z-index: 10; + padding: 0 10px; + background-color: #FFF; + min-width: 140px; } - .delete-message { - display: none; - cursor: pointer; + &:after { + content: " "; + display: block; + position: absolute; + top: -20px; + left: 0; + width: 100%; + border-top: 1px solid #ddd; } - &.own:hover:not(.system) .delete-message { - display: inline-block; + } + .edit-message { + display: none; + cursor: pointer; + } + &.own:hover:not(.system) .edit-message { + display: inline-block; + } + .delete-message { + display: none; + cursor: pointer; + } + &.own:hover:not(.system) .delete-message { + display: inline-block; + } + .user { + display: inline-block; + font-weight: 600; + color: #444444; + margin-right: 5px; + &:hover { + color: #333; } + } + .thumb { + position: absolute; + left: 0; + top: 0; + display: block; + width: 40px; + height: 40px; + } + .info { + font-size: 12px; + color: @info-font-color; + } + &.sequential { + margin-top: 5px; + min-height: 20px; .user { - display: inline-block; - font-weight: 600; - color: #444444; - margin-right: 5px; - &:hover { - color: #333; - } + display: none; } .thumb { - position: absolute; - left: 0; - top: 0; - display: block; - width: 40px; - height: 40px; + display: none; } .info { - font-size: 12px; - color: @info-font-color; - } - &.sequential { - margin-top: 5px; - min-height: 20px; - .user { + position: absolute; + text-align: right; + left: -20px; + width: 65px; + .time { display: none; } - .thumb { - display: none; + .edited { + display: inline-block; } - .info { - position: absolute; - text-align: right; - left: -20px; - width: 65px; - .time { - display: none; - } - .edited { - display: inline-block; - } - .edit-message { - float: left; - margin-left: 1px; - } - .delete-message { - float: left; - } + .edit-message { + float: left; + margin-left: 1px; } - &:hover { - .time { - display: inline-block; - } - .edited { - display: none; - } + .delete-message { + float: left; } } - &.system { - .body { - color: @info-font-color; - font-style: italic; - text-transform: lowercase; - em { - font-weight: 600; - } + &:hover { + .time { + display: inline-block; } - } - .avatar-initials { - line-height: 40px; - } - a { - color: @link-font-color; - font-weight: 400; - &:hover { - color: darken(@link-font-color, 10%); - text-decoration: underline; + .edited { + display: none; } } + } + &.system { .body { - opacity: 1; - .transition(opacity 1s linear); + color: @info-font-color; + font-style: italic; + text-transform: lowercase; + em { + font-weight: 600; + } } - &.temp .body { - opacity: .5; + } + .avatar-initials { + line-height: 40px; + } + a { + color: @link-font-color; + font-weight: 400; + &:hover { + color: darken(@link-font-color, 10%); + text-decoration: underline; } } + .body { + opacity: 1; + .transition(opacity 1s linear); + } + &.temp .body { + opacity: .5; + } } // FLEX-TAB and FLEX-TAB views @@ -2700,7 +2701,7 @@ a.github-fork { > div { position: relative; } - .icon-plus { + .icon-plus { position: absolute; top: 11px; left: 8px; diff --git a/client/views/app/message.coffee b/client/views/app/message.coffee index 06b17f5c5169..94bc4959f0e1 100644 --- a/client/views/app/message.coffee +++ b/client/views/app/message.coffee @@ -80,8 +80,8 @@ Template.message.onViewRendered = (context) -> if not lastNode.nextElementSibling? if lastNode.classList.contains('own') is true - view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom = true + view.parentView.parentView.parentView.parentView.parentView.templateInstance?().atBottom = true else - if view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom isnt true + if view.parentView.parentView.parentView.parentView.parentView.templateInstance?().atBottom isnt true newMessage = document.querySelector(".new-message") newMessage.className = "new-message" diff --git a/client/views/app/room.coffee b/client/views/app/room.coffee index e027c67fb0f2..8e604c903350 100644 --- a/client/views/app/room.coffee +++ b/client/views/app/room.coffee @@ -6,6 +6,9 @@ Template.room.helpers tQuickSearch: -> return t('Quick_Search') + searchResult: -> + return Template.instance().searchResult.get() + favorite: -> sub = ChatSubscription.findOne { rid: this._id }, { fields: { f: 1 } } return 'icon-star favorite-room' if sub?.f? and sub.f @@ -275,6 +278,18 @@ Template.room.helpers Template.room.events + "keyup #room-search": _.debounce (e, t) -> + t.searchResult.set undefined + value = e.target.value.trim() + if value is '' + return + + Tracker.nonreactive -> + Meteor.call 'messageSearch', value, Session.get('openedRoom'), (error, result) -> + if result? and (result.messages?.length > 0 or result.users?.length > 0 or result.channels?.length > 0) + t.searchResult.set result + , 1000 + "touchstart .message": (e, t) -> message = this._arguments[1] doLongTouch = -> @@ -294,10 +309,11 @@ Template.room.events "click .upload-progress-item > a": -> Session.set "uploading-cancel-#{this.id}", true - "click .flex-tab .more": (event) -> + "click .flex-tab .more": (event, t) -> if (Session.get('flexOpened')) Session.set('rtcLayoutmode', 0) Session.set('flexOpened',false) + t.searchResult.set undefined else Session.set('flexOpened', true) @@ -630,6 +646,7 @@ Template.room.onCreated -> # this.typing = new msgTyping this.data._id this.showUsersOffline = new ReactiveVar false this.atBottom = true + this.searchResult = new ReactiveVar self = @ diff --git a/client/views/app/room.html b/client/views/app/room.html index c5fb4a3c1be8..006a65b86190 100644 --- a/client/views/app/room.html +++ b/client/views/app/room.html @@ -129,55 +129,69 @@

- {{#if canAddUser}} -
- +
+ - {{else}} - {{#if isChannel}} - - -
- {{/if}} - {{/if}} +
{{#if flexOpened}}
- {{#if isGroupChat}} -
- {{#with roomUsers}} -
-

{{_ "Members_List"}}

-

- {{{_ "Showing_online_users" total_online=totalOnline total=total}}} - {{!----}} -

-
- - {{/with}} -
-
- {{> userInfo user=flexUserInfo showAll=true}} -
+ {{#if searchResult.messages}} +
    + {{#each searchResult.messages}} + {{#nrr nrrargs 'message' .}}{{/nrr}} + {{/each}} +
+ {{else}} -
- {{> userInfo user=flexUserInfo video=true}} -
+ {{#if isGroupChat}} +
+ {{#with roomUsers}} +
+

{{_ "Members_List"}}

+

+ {{{_ "Showing_online_users" total_online=totalOnline total=total}}} + {{!----}} +

+ {{#if canAddUser}} +
+
+ +
+
+ {{/if}} +
+ + {{/with}} +
+
+ {{> userInfo user=flexUserInfo showAll=true}} +
+ {{else}} +
+ {{> userInfo user=flexUserInfo video=true}} +
+ {{/if}} {{/if}}
{{/if}} diff --git a/server/methods/searchMessage.coffee b/server/methods/searchMessage.coffee new file mode 100644 index 000000000000..8c3003ebd46e --- /dev/null +++ b/server/methods/searchMessage.coffee @@ -0,0 +1,110 @@ +Meteor.methods + messageSearch: (text, rid) -> + ### + text = 'from:rodrigo mention:gabriel chat' + ### + + # console.log '[method] -> messageSearch', text + + result = + messages: [] + users: [] + channels: [] + + query = {} + options = + sort: + ts: -1 + limit: 20 + + # Query for senders + from = [] + text = text.replace /from:([a-z0-9.-_]+)/ig, (match, username, index) -> + from.push username + return '' + + if from.length > 0 + query['u.username'] = + $regex: from.join('|') + $options: 'i' + + + # Query for mentions + mention = [] + text = text.replace /mention:([a-z0-9.-_]+)/ig, (match, username, index) -> + mention.push username + return '' + + if mention.length > 0 + query['mentions.username'] = + $regex: mention.join('|') + $options: 'i' + + + # Query in message text + text = text.trim().replace(/\s\s/g, ' ') + if text isnt '' + query.$text = + $search: text + + options.fields = + score: + $meta: "textScore" + + options.sort = + score: + $meta: 'textScore' + + if Object.keys(query).length > 0 + # Filter by room + if rid? + query.rid = rid + try + if Meteor.call('canAccessRoom', rid, this.userId) isnt false + result.messages = ChatMessage.find(query, options).fetch() + + # ### + # # USERS + # ### + # if from.length is 0 and mention.length is 0 and text isnt '' + # query = + # username: + # $regex: text + # $options: 'i' + + # options = + # limit: 5 + # sort: + # username: 1 + # fields: + # username: 1 + # name: 1 + # status: 1 + # utcOffset: 1 + + # result.users = Meteor.users.find(query, options).fetch() + + + # ### + # # CHANNELS + # ### + # if from.length is 0 and mention.length is 0 and text isnt '' + # query = + # t: 'c' + # name: + # $regex: text + # $options: 'i' + + # options = + # limit: 5 + # sort: + # name: 1 + # fields: + # username: 1 + # name: 1 + # status: 1 + # utcOffset: 1 + + # result.channels = ChatRoom.find(query, options).fetch() + + return result \ No newline at end of file diff --git a/server/startup/indexes.coffee b/server/startup/indexes.coffee index 9d9512efb369..28eca27eefa1 100644 --- a/server/startup/indexes.coffee +++ b/server/startup/indexes.coffee @@ -14,3 +14,4 @@ Meteor.startup -> try ChatMessage._ensureIndex { 'ets': 1 }, { sparse: 1 } catch e then console.log e try ChatMessage._ensureIndex { 'rid': 1, 't': 1, 'u._id': 1 } catch e then console.log e try ChatMessage._ensureIndex { 'expireAt': 1 }, { expireAfterSeconds: 0 } catch e then console.log e + try ChatMessage._ensureIndex { 'msg': 'text' } catch e then console.log e