diff sat_frontends/quick_frontend/quick_chat.py @ 2851:7764383a968c

quick_frontend (widget, chat): implementation of new sync mechanism, first draft: QuickWidget implement base of sync mechanism with a sync property which can be overriden, and resync method which is called when resynchronisation is needed. When resync is required, chat widget get missing occupant and history elements A new callable argument can be used with historyPrint, when set it is called when history has been fully printed.
author Goffi <goffi@goffi.org>
date Sun, 10 Mar 2019 18:03:11 +0100
parents 272dc905ff20
children 33a69ee7fbb7
line wrap: on
line diff
--- a/sat_frontends/quick_frontend/quick_chat.py	Sun Mar 10 18:03:02 2019 +0100
+++ b/sat_frontends/quick_frontend/quick_chat.py	Sun Mar 10 18:03:11 2019 +0100
@@ -281,6 +281,9 @@
         self.type = type_
         self.encrypted = False  # True if this session is currently encrypted
         self._locked = False
+        # True when resync is in progress, avoid resynchronising twice when resync is called
+        # and history is still being updated. For internal use only
+        self._resync_lock = False
         self.setLocked()
         if type_ == C.CHAT_GROUP:
             if target.resource:
@@ -363,6 +366,43 @@
     def contact_list(self):
         return self.host.contact_lists[self.profile]
 
+    ## synchornisation handling ##
+
+    @quick_widgets.QuickWidget.sync.setter
+    def sync(self, state):
+        quick_widgets.QuickWidget.sync.fset(self, state)
+        if not state:
+            self.setLocked()
+
+    def _resyncComplete(self):
+        self.sync = True
+        self._resync_lock = False
+
+    def resync(self):
+        if self._resync_lock:
+            return
+        self._resync_lock = True
+        log.debug(u"resynchronising {self}".format(self=self))
+        for mess in reversed(self.messages.values()):
+            if mess.type == C.MESS_TYPE_INFO:
+                continue
+            last_message = mess
+            break
+        else:
+            # we have no message yet, we can get normal history
+            self.historyPrint(callback=self._resyncComplete, profile=self.profile)
+            return
+        if self.type == C.CHAT_GROUP:
+            self.occupants.clear()
+            self.host.bridge.mucOccupantsGet(
+                unicode(self.target), self.profile, callback=self.updateOccupants,
+                errback=log.error)
+        self.historyPrint(
+            size=C.HISTORY_LIMIT_NONE,
+            filters={'timestamp_start': last_message.timestamp},
+            callback=self._resyncComplete,
+            profile=self.profile)
+
     ## Widget management ##
 
     def __unicode__(self):
@@ -428,9 +468,11 @@
     ## occupants ##
 
     def setOccupants(self, occupants):
-        """set the whole list of occupants"""
+        """Set the whole list of occupants"""
         assert len(self.occupants) == 0
         for nick, data in occupants.iteritems():
+            log.debug(u"adding occupant {nick} to {room}".format(
+                nick=nick, room=self.target))
             self.occupants[nick] = Occupant(self, data, self.profile)
 
     def updateOccupants(self, occupants):
@@ -523,12 +565,14 @@
         """
         self.setUnlocked()
 
-    def historyPrint(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile="@NONE@"):
+    def historyPrint(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, callback=None,
+                     profile="@NONE@"):
         """Print the current history
 
         Note: self.setUnlocked will be called once history is printed
         @param size (int): number of messages
         @param search (str): pattern to filter the history results
+        @param callback(callable, None): method to call when history has been printed
         @param profile (str): %(doc_profile)s
         """
         if filters is None:
@@ -589,10 +633,14 @@
                     profile,
                 )
             self._onHistoryPrinted()
+            if callback is not None:
+                callback()
 
         def _historyGetEb(err):
             log.error(_(u"Can't get history: {}").format(err))
             self._onHistoryPrinted()
+            if callback is not None:
+                callback()
 
         self.host.bridge.historyGet(
             unicode(self.host.profiles[profile].whoami.bare),