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}}
-
{{#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