Reset badge count to zero when last active time is bumped

This commit is contained in:
David Baker 2015-01-28 11:55:49 +00:00
parent f7c4daa8f9
commit 273b12729b
4 changed files with 76 additions and 3 deletions

View File

@ -86,6 +86,10 @@ class PresenceHandler(BaseHandler):
"changed_presencelike_data", self.changed_presencelike_data "changed_presencelike_data", self.changed_presencelike_data
) )
# outbound signal from the presence module to advertise when a user's
# presence has changed
distributor.declare("user_presence_changed")
self.distributor = distributor self.distributor = distributor
self.federation = hs.get_replication_layer() self.federation = hs.get_replication_layer()
@ -603,6 +607,7 @@ class PresenceHandler(BaseHandler):
room_ids=room_ids, room_ids=room_ids,
statuscache=statuscache, statuscache=statuscache,
) )
yield self.distributor.fire("user_presence_changed", user, statuscache)
@defer.inlineCallbacks @defer.inlineCallbacks
def _push_presence_remote(self, user, destination, state=None): def _push_presence_remote(self, user, destination, state=None):

View File

@ -54,6 +54,9 @@ class Pusher(object):
self.failing_since = failing_since self.failing_since = failing_since
self.alive = True self.alive = True
# The last value of last_active_time that we saw
self.last_last_active_time = 0
@defer.inlineCallbacks @defer.inlineCallbacks
def _actions_for_event(self, ev): def _actions_for_event(self, ev):
""" """
@ -273,6 +276,22 @@ class Pusher(object):
""" """
pass pass
def reset_badge_count(self):
pass
def presence_changed(self, state):
"""
We clear badge counts whenever a user's last_active time is bumped
This is by no means perfect but I think it's the best we can do
without read receipts.
"""
if 'last_active' in state.state:
last_active = state.state['last_active']
if last_active > self.last_last_active_time:
logger.info("Resetting badge count for %s", self.user_name)
self.reset_badge_count()
self.last_last_active_time = last_active
def _value_for_dotted_key(dotted_key, event): def _value_for_dotted_key(dotted_key, event):
parts = dotted_key.split(".") parts = dotted_key.split(".")

View File

@ -71,11 +71,12 @@ class HttpPusher(Pusher):
# we may have to fetch this over federation and we # we may have to fetch this over federation and we
# can't trust it anyway: is it worth it? # can't trust it anyway: is it worth it?
#'from_display_name': 'Steve Stevington' #'from_display_name': 'Steve Stevington'
#'counts': { -- we don't mark messages as read yet so 'counts': { #-- we don't mark messages as read yet so
# we have no way of knowing # we have no way of knowing
# 'unread': 1, # Just set the badge to 1 until we have read receipts
'unread': 1,
# 'missed_calls': 2 # 'missed_calls': 2
# }, },
'devices': [ 'devices': [
{ {
'app_id': self.app_id, 'app_id': self.app_id,
@ -111,3 +112,34 @@ class HttpPusher(Pusher):
if 'rejected' in resp: if 'rejected' in resp:
rejected = resp['rejected'] rejected = resp['rejected']
defer.returnValue(rejected) defer.returnValue(rejected)
@defer.inlineCallbacks
def reset_badge_count(self):
d = {
'notification': {
'id': '',
'type': None,
'from': '',
'counts': {
'unread': 0,
'missed_calls': 0
},
'devices': [
{
'app_id': self.app_id,
'pushkey': self.pushkey,
'pushkey_ts': long(self.pushkey_ts / 1000),
'data': self.data_minus_url,
}
]
}
}
try:
resp = yield self.httpCli.post_json_get_json(self.url, d)
except:
logger.exception("Failed to push %s ", self.url)
defer.returnValue(False)
rejected = []
if 'rejected' in resp:
rejected = resp['rejected']
defer.returnValue(rejected)

View File

@ -18,6 +18,7 @@ from twisted.internet import defer
from httppusher import HttpPusher from httppusher import HttpPusher
from synapse.push import PusherConfigException from synapse.push import PusherConfigException
from synapse.api.constants import PresenceState
import logging import logging
import json import json
@ -32,6 +33,22 @@ class PusherPool:
self.pushers = {} self.pushers = {}
self.last_pusher_started = -1 self.last_pusher_started = -1
distributor = self.hs.get_distributor()
distributor.observe(
"user_presence_changed", self.user_presence_changed
)
@defer.inlineCallbacks
def user_presence_changed(self, user, state):
user_name = user.to_string()
# until we have read receipts, pushers use this to reset a user's
# badge counters to zero
for p in self.pushers.values():
if p.user_name == user_name:
yield p.presence_changed(state)
@defer.inlineCallbacks @defer.inlineCallbacks
def start(self): def start(self):
pushers = yield self.store.get_all_pushers() pushers = yield self.store.get_all_pushers()