comparison 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
comparison
equal deleted inserted replaced
2850:272dc905ff20 2851:7764383a968c
279 assert type_ in (C.CHAT_ONE2ONE, C.CHAT_GROUP) 279 assert type_ in (C.CHAT_ONE2ONE, C.CHAT_GROUP)
280 self.current_target = target 280 self.current_target = target
281 self.type = type_ 281 self.type = type_
282 self.encrypted = False # True if this session is currently encrypted 282 self.encrypted = False # True if this session is currently encrypted
283 self._locked = False 283 self._locked = False
284 # True when resync is in progress, avoid resynchronising twice when resync is called
285 # and history is still being updated. For internal use only
286 self._resync_lock = False
284 self.setLocked() 287 self.setLocked()
285 if type_ == C.CHAT_GROUP: 288 if type_ == C.CHAT_GROUP:
286 if target.resource: 289 if target.resource:
287 raise exceptions.InternalError( 290 raise exceptions.InternalError(
288 u"a group chat entity can't have a resource" 291 u"a group chat entity can't have a resource"
361 364
362 @property 365 @property
363 def contact_list(self): 366 def contact_list(self):
364 return self.host.contact_lists[self.profile] 367 return self.host.contact_lists[self.profile]
365 368
369 ## synchornisation handling ##
370
371 @quick_widgets.QuickWidget.sync.setter
372 def sync(self, state):
373 quick_widgets.QuickWidget.sync.fset(self, state)
374 if not state:
375 self.setLocked()
376
377 def _resyncComplete(self):
378 self.sync = True
379 self._resync_lock = False
380
381 def resync(self):
382 if self._resync_lock:
383 return
384 self._resync_lock = True
385 log.debug(u"resynchronising {self}".format(self=self))
386 for mess in reversed(self.messages.values()):
387 if mess.type == C.MESS_TYPE_INFO:
388 continue
389 last_message = mess
390 break
391 else:
392 # we have no message yet, we can get normal history
393 self.historyPrint(callback=self._resyncComplete, profile=self.profile)
394 return
395 if self.type == C.CHAT_GROUP:
396 self.occupants.clear()
397 self.host.bridge.mucOccupantsGet(
398 unicode(self.target), self.profile, callback=self.updateOccupants,
399 errback=log.error)
400 self.historyPrint(
401 size=C.HISTORY_LIMIT_NONE,
402 filters={'timestamp_start': last_message.timestamp},
403 callback=self._resyncComplete,
404 profile=self.profile)
405
366 ## Widget management ## 406 ## Widget management ##
367 407
368 def __unicode__(self): 408 def __unicode__(self):
369 return u"Chat Widget [target: {}, type: {}, profile: {}]".format( 409 return u"Chat Widget [target: {}, type: {}, profile: {}]".format(
370 self.target, self.type, self.profile 410 self.target, self.type, self.profile
426 return self.current_target 466 return self.current_target
427 467
428 ## occupants ## 468 ## occupants ##
429 469
430 def setOccupants(self, occupants): 470 def setOccupants(self, occupants):
431 """set the whole list of occupants""" 471 """Set the whole list of occupants"""
432 assert len(self.occupants) == 0 472 assert len(self.occupants) == 0
433 for nick, data in occupants.iteritems(): 473 for nick, data in occupants.iteritems():
474 log.debug(u"adding occupant {nick} to {room}".format(
475 nick=nick, room=self.target))
434 self.occupants[nick] = Occupant(self, data, self.profile) 476 self.occupants[nick] = Occupant(self, data, self.profile)
435 477
436 def updateOccupants(self, occupants): 478 def updateOccupants(self, occupants):
437 """Update occupants list 479 """Update occupants list
438 480
521 unlock the widget, and can be used to refresh or scroll down 563 unlock the widget, and can be used to refresh or scroll down
522 the focus after the history is printed 564 the focus after the history is printed
523 """ 565 """
524 self.setUnlocked() 566 self.setUnlocked()
525 567
526 def historyPrint(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile="@NONE@"): 568 def historyPrint(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, callback=None,
569 profile="@NONE@"):
527 """Print the current history 570 """Print the current history
528 571
529 Note: self.setUnlocked will be called once history is printed 572 Note: self.setUnlocked will be called once history is printed
530 @param size (int): number of messages 573 @param size (int): number of messages
531 @param search (str): pattern to filter the history results 574 @param search (str): pattern to filter the history results
575 @param callback(callable, None): method to call when history has been printed
532 @param profile (str): %(doc_profile)s 576 @param profile (str): %(doc_profile)s
533 """ 577 """
534 if filters is None: 578 if filters is None:
535 filters = {} 579 filters = {}
536 if size == 0: 580 if size == 0:
587 type_, 631 type_,
588 extra, 632 extra,
589 profile, 633 profile,
590 ) 634 )
591 self._onHistoryPrinted() 635 self._onHistoryPrinted()
636 if callback is not None:
637 callback()
592 638
593 def _historyGetEb(err): 639 def _historyGetEb(err):
594 log.error(_(u"Can't get history: {}").format(err)) 640 log.error(_(u"Can't get history: {}").format(err))
595 self._onHistoryPrinted() 641 self._onHistoryPrinted()
642 if callback is not None:
643 callback()
596 644
597 self.host.bridge.historyGet( 645 self.host.bridge.historyGet(
598 unicode(self.host.profiles[profile].whoami.bare), 646 unicode(self.host.profiles[profile].whoami.bare),
599 unicode(target), 647 unicode(target),
600 size, 648 size,