Skip to content
Snippets Groups Projects
Commit 600fd068 authored by Rodrigo Nascimento's avatar Rodrigo Nascimento
Browse files

Improve unread behaviour

parent 2fe71b4d
No related merge requests found
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
histories[rid] = histories[rid] =
hasMore: ReactiveVar true hasMore: ReactiveVar true
isLoading: ReactiveVar false isLoading: ReactiveVar false
unreadNotLoaded: ReactiveVar 0
loaded: 0 loaded: 0
return histories[rid] return histories[rid]
...@@ -28,11 +29,19 @@ ...@@ -28,11 +29,19 @@
else else
ts = new Date ts = new Date
Meteor.call 'loadHistory', rid, ts, limit, 0, (err, result) -> ls = undefined
subscription = ChatSubscription.findOne rid: rid
if subscription?
ls = subscription.ls
Meteor.call 'loadHistory', rid, ts, limit, ls, (err, result) ->
room.unreadNotLoaded.set result.unreadNotLoaded
wrapper = $('.messages-box .wrapper').get(0) wrapper = $('.messages-box .wrapper').get(0)
previousHeight = wrapper.scrollHeight previousHeight = wrapper.scrollHeight
ChatMessage.insert item for item in result ChatMessage.insert item for item in result.messages
heightDiff = wrapper.scrollHeight - previousHeight heightDiff = wrapper.scrollHeight - previousHeight
wrapper.scrollTop += heightDiff wrapper.scrollTop += heightDiff
...@@ -41,8 +50,8 @@ ...@@ -41,8 +50,8 @@
readMessage.refreshUnreadMark(rid, true) readMessage.refreshUnreadMark(rid, true)
room.isLoading.set false room.isLoading.set false
room.loaded += result.length room.loaded += result.messages.length
if result.length < limit if result.messages.length < limit
room.hasMore.set false room.hasMore.set false
hasMore = (rid) -> hasMore = (rid) ->
...@@ -68,6 +77,7 @@ ...@@ -68,6 +77,7 @@
histories[rid].isLoading.set false histories[rid].isLoading.set false
histories[rid].loaded = 0 histories[rid].loaded = 0
getRoom: getRoom
getMore: getMore getMore: getMore
getMoreIfIsEmpty: getMoreIfIsEmpty getMoreIfIsEmpty: getMoreIfIsEmpty
hasMore: hasMore hasMore: hasMore
......
...@@ -124,7 +124,6 @@ onDeleteMessageStream = (msg) -> ...@@ -124,7 +124,6 @@ onDeleteMessageStream = (msg) ->
openedRooms[typeName] = openedRooms[typeName] =
active: false active: false
ready: false ready: false
unreadCount: new ReactiveVar 0
unreadSince: new ReactiveVar undefined unreadSince: new ReactiveVar undefined
setRoomExpireExcept typeName setRoomExpireExcept typeName
......
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
- The default method *read* has a delay of 2000ms to prevent multiple reads and to user be able to see the mark - The default method *read* has a delay of 2000ms to prevent multiple reads and to user be able to see the mark
### ###
Meteor.startup -> # Meteor.startup ->
window.addEventListener 'focus', -> # window.addEventListener 'focus', ->
readMessage.refreshUnreadMark(undefined, true) # readMessage.refreshUnreadMark(undefined, true)
@readMessage = new class @readMessage = new class
constructor: -> constructor: ->
...@@ -37,7 +37,7 @@ Meteor.startup -> ...@@ -37,7 +37,7 @@ Meteor.startup ->
# Only read messages if user saw the first unread message # Only read messages if user saw the first unread message
position = $('.message.first-unread').position() position = $('.message.first-unread').position()
if (position? and position.top >= 0) or room.unreadCount.get() is 0 if (position? and position.top >= 0) or not room.unreadSince.get()?
Meteor.call 'readMessages', rid, -> Meteor.call 'readMessages', rid, ->
self.refreshUnreadMark() self.refreshUnreadMark()
...@@ -69,30 +69,51 @@ Meteor.startup -> ...@@ -69,30 +69,51 @@ Meteor.startup ->
if not room? if not room?
return return
room.loadingUnread = true
$roomDom = $(room.dom) $roomDom = $(room.dom)
$roomDom.find('.message.first-unread').addClass('first-unread-opaque') $roomDom.find('.message.first-unread').addClass('first-unread-opaque')
if not subscription.alert and subscription.unread is 0 if not subscription.alert and subscription.unread is 0
room.unreadLoading = false room.unreadSince.set undefined
room.unreadCount.set 0
return return
if not force? and subscription.rid is Session.get('openedRoom') and document.hasFocus() if not force? and subscription.rid is Session.get('openedRoom') and document.hasFocus()
return return
$roomDom.find('.message.first-unread').removeClass('first-unread').removeClass('first-unread-opaque') $roomDom.find('.message.first-unread').removeClass('first-unread').removeClass('first-unread-opaque')
@disable()
Meteor.call 'countAndFirstId', subscription.rid, (error, data) -> lastReadRecord = ChatMessage.findOne
room.unreadLoading = false rid: subscription.rid
room.unreadCount.set data.count ts:
room.unreadSince.set data.since $lt: subscription.ls
room.unreadFirstId = data.firstUnreadId # 'u._id':
# $ne: Meteor.userId()
self.enable() ,
if data.firstUnreadId? sort:
$roomDom.find('.message#'+data.firstUnreadId).addClass('first-unread') ts: -1
if not lastReadRecord? and RoomHistoryManager.getRoom(room.rid).unreadNotLoaded.get() is 0
lastReadRecord =
ts: new Date(0)
if lastReadRecord? or RoomHistoryManager.getRoom(room.rid).unreadNotLoaded.get() > 0
room.unreadSince.set subscription.ls
else
room.unreadSince.set undefined
if lastReadRecord?
firstUnreadRecord = ChatMessage.findOne
rid: subscription.rid
ts:
$gt: lastReadRecord.ts
'u._id':
$ne: Meteor.userId()
,
sort:
ts: 1
if firstUnreadRecord?
room.unreadFirstId = firstUnreadRecord._id
$roomDom.find('.message#'+firstUnreadRecord._id).addClass('first-unread')
Meteor.startup -> Meteor.startup ->
......
...@@ -38,9 +38,6 @@ openRoom = (type, name) -> ...@@ -38,9 +38,6 @@ openRoom = (type, name) ->
Session.set 'editRoomTitle', false Session.set 'editRoomTitle', false
readMessage.disable() readMessage.disable()
Meteor.setTimeout ->
readMessage.refreshUnreadMark(undefined, true)
, 1000
Meteor.setTimeout -> Meteor.setTimeout ->
readMessage.readNow() readMessage.readNow()
, 2000 , 2000
......
...@@ -46,7 +46,7 @@ Meteor.startup -> ...@@ -46,7 +46,7 @@ Meteor.startup ->
Tracker.autorun -> Tracker.autorun ->
siteName = RocketChat.settings.get 'Site_Name' siteName = RocketChat.settings.get 'Site_Name'
unread = Session.get 'unread' unread = Session.get 'unread'
fireGlobalEvent 'unread-changed', unread fireGlobalEvent 'unread-changed', unread
favico?.badge unread, bgColor: if typeof unread isnt 'number' then '#3d8a3a' else '#ac1b1b' favico?.badge unread, bgColor: if typeof unread isnt 'number' then '#3d8a3a' else '#ac1b1b'
......
...@@ -2270,11 +2270,9 @@ a.github-fork { ...@@ -2270,11 +2270,9 @@ a.github-fork {
.message { .message {
font-size: 14px; font-size: 14px;
padding-left: 50px; padding: 8px 20px 8px 70px;
position: relative; position: relative;
line-height: 20px; line-height: 20px;
margin: 12px 20px 5px;
margin-top: 12px;
min-height: 40px; min-height: 40px;
&:nth-child(1) { &:nth-child(1) {
margin-top: 0; margin-top: 0;
...@@ -2331,8 +2329,8 @@ a.github-fork { ...@@ -2331,8 +2329,8 @@ a.github-fork {
} }
.thumb { .thumb {
position: absolute; position: absolute;
left: 0; left: 20px;
top: 0; top: 10px;
display: block; display: block;
width: 40px; width: 40px;
height: 40px; height: 40px;
...@@ -2341,7 +2339,6 @@ a.github-fork { ...@@ -2341,7 +2339,6 @@ a.github-fork {
font-size: 12px; font-size: 12px;
} }
&.sequential { &.sequential {
margin-top: 14px;
min-height: 20px; min-height: 20px;
.user { .user {
display: none; display: none;
...@@ -2352,7 +2349,7 @@ a.github-fork { ...@@ -2352,7 +2349,7 @@ a.github-fork {
.info { .info {
position: absolute; position: absolute;
text-align: right; text-align: right;
left: -20px; left: 0px;
width: 65px; width: 65px;
.time { .time {
display: none; display: none;
......
...@@ -280,6 +280,9 @@ Template.room.helpers ...@@ -280,6 +280,9 @@ Template.room.helpers
room = ChatRoom.findOne(this._id, { reactive: false }) room = ChatRoom.findOne(this._id, { reactive: false })
return RoomManager.openedRooms[room.t + room.name] return RoomManager.openedRooms[room.t + room.name]
unreadCount: ->
return RoomHistoryManager.getRoom(@_id).unreadNotLoaded.get() + Template.instance().unreadCount.get()
formatUnreadSince: -> formatUnreadSince: ->
room = ChatRoom.findOne(this._id, { reactive: false }) room = ChatRoom.findOne(this._id, { reactive: false })
room = RoomManager.openedRooms[room.t + room.name] room = RoomManager.openedRooms[room.t + room.name]
...@@ -663,6 +666,7 @@ Template.room.onCreated -> ...@@ -663,6 +666,7 @@ Template.room.onCreated ->
this.showUsersOffline = new ReactiveVar false this.showUsersOffline = new ReactiveVar false
this.atBottom = true this.atBottom = true
this.searchResult = new ReactiveVar this.searchResult = new ReactiveVar
this.unreadCount = new ReactiveVar 0
self = @ self = @
...@@ -680,10 +684,23 @@ Template.room.onRendered -> ...@@ -680,10 +684,23 @@ Template.room.onRendered ->
template = this template = this
wrapperOffset = $('.messages-box > .wrapper').offset()
onscroll = _.throttle -> onscroll = _.throttle ->
template.atBottom = wrapper.scrollTop >= wrapper.scrollHeight - wrapper.clientHeight template.atBottom = wrapper.scrollTop >= wrapper.scrollHeight - wrapper.clientHeight
, 200 , 200
updateUnreadCount = _.throttle ->
firstMessageOnScreen = document.elementFromPoint(wrapperOffset.left+1, wrapperOffset.top+50)
if firstMessageOnScreen?.id?
firstMessage = ChatMessage.findOne firstMessageOnScreen.id
if firstMessage?
subscription = ChatSubscription.findOne rid: template.data._id
template.unreadCount.set ChatMessage.find({rid: template.data._id, ts: {$lt: firstMessage.ts, $gt: subscription.ls}}).count()
else
template.unreadCount.set 0
, 300
Meteor.setInterval -> Meteor.setInterval ->
if template.atBottom if template.atBottom
wrapper.scrollTop = wrapper.scrollHeight - wrapper.clientHeight wrapper.scrollTop = wrapper.scrollHeight - wrapper.clientHeight
...@@ -701,6 +718,7 @@ Template.room.onRendered -> ...@@ -701,6 +718,7 @@ Template.room.onRendered ->
wrapper.addEventListener 'scroll', -> wrapper.addEventListener 'scroll', ->
template.atBottom = false template.atBottom = false
onscroll() onscroll()
updateUnreadCount()
wrapper.addEventListener 'mousewheel', -> wrapper.addEventListener 'mousewheel', ->
template.atBottom = false template.atBottom = false
......
...@@ -38,13 +38,15 @@ ...@@ -38,13 +38,15 @@
</div> </div>
{{/each}} {{/each}}
</div> </div>
{{#if roomManager.unreadCount.get}} {{#if unreadCount}}
<div class="unread-bar"> {{#if roomManager.unreadSince.get}}
{{_ "S_new_messages_since_s" roomManager.unreadCount.get formatUnreadSince}} <div class="unread-bar">
<a> {{_ "S_new_messages_since_s" unreadCount formatUnreadSince}}
{{_ "Mark_as_read"}} <a>
</a> {{_ "Mark_as_read"}}
</div> </a>
</div>
{{/if}}
{{/if}} {{/if}}
<div class="messages-box"> <div class="messages-box">
<div class="wrapper"> <div class="wrapper">
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
else else
ts = new Date ts = new Date
Meteor.call 'loadHistory', rid, ts, limit, 0, (err, result) -> Meteor.call 'loadHistory', rid, ts, limit, undefined, (err, result) ->
ChatMessage.insert item for item in result ChatMessage.insert item for item in result.messages
room.isLoading.set false room.isLoading.set false
room.loaded += result.length room.loaded += result.messages.length
if result.length < limit if result.messages.length < limit
room.hasMore.set false room.hasMore.set false
hasMore = (rid) -> hasMore = (rid) ->
......
Meteor.methods
countAndFirstId: (rid) ->
subscription = ChatSubscription.findOne
rid: rid
'u._id': Meteor.userId()
query =
rid: rid
ts:
$gt: subscription.ls
'u._id':
$ne: Meteor.userId()
options =
sort:
ts: 1
limit: 1
firstUnread = ChatMessage.find(query, options).fetch()[0]
if not firstUnread?
return {
firstUnreadId: undefined
count: 0
since: subscription.ls
}
options =
sort:
ts: 1
count = ChatMessage.find(query, options).count()
return {
firstUnreadId: firstUnread._id
count: count
since: subscription.ls
}
Meteor.methods Meteor.methods
loadHistory: (rid, end, limit=20, skip=0) -> loadHistory: (rid, end, limit=20, ls) ->
fromId = Meteor.userId() fromId = Meteor.userId()
# console.log '[methods] loadHistory -> '.green, 'fromId:', fromId, 'rid:', rid, 'end:', end, 'limit:', limit, 'skip:', skip # console.log '[methods] loadHistory -> '.green, 'fromId:', fromId, 'rid:', rid, 'end:', end, 'limit:', limit, 'skip:', skip
...@@ -16,9 +16,22 @@ Meteor.methods ...@@ -16,9 +16,22 @@ Meteor.methods
sort: sort:
ts: -1 ts: -1
limit: limit limit: limit
skip: skip
if not RocketChat.settings.get 'Message_ShowEditedStatus' if not RocketChat.settings.get 'Message_ShowEditedStatus'
options.fields = { ets: 0 } options.fields = { ets: 0 }
return ChatMessage.find(query, options).fetch() messages = ChatMessage.find(query, options).fetch()
unreadNotLoaded = 0
if ls?
fistMessage = messages[messages.length - 1]
if fistMessage.ts > ls
query.ts.$lt = fistMessage.ts
query.ts.$gt = ls
delete options.limit
unreadNotLoaded = ChatMessage.find(query, options).count()
return {
messages: messages
unreadNotLoaded: unreadNotLoaded
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment