comparison src/browser/libervia_main.py @ 716:3b91225b457a

server + browser side: blogging refactoring (draft), huge commit sorry: /!\ everything is not working yet, group blog is not working for now - adaptation to backend changes - frontend commons part of blog have been moved to QuickFrontend - (editors) button "WYSIWYG edition" renamed to "preview" - (editors) Shift + [ENTER] is now used to send a text message, [ENTER] to finish a ligne normally - (editors) fixed modifiers handling - global simplification, resulting of the refactoring - with backend refactoring, we are now using PEP again, XEP-0277 compatibility is restored \o/
author Goffi <goffi@goffi.org>
date Sun, 16 Aug 2015 01:51:12 +0200
parents 03e9fe91081c
children 5745b5e6586a
comparison
equal deleted inserted replaced
715:b2465423c76e 716:3b91225b457a
36 from sat_frontends.tools import jid 36 from sat_frontends.tools import jid
37 from sat_frontends.tools import host_listener 37 from sat_frontends.tools import host_listener
38 from sat.core.i18n import _ 38 from sat.core.i18n import _
39 39
40 from pyjamas.ui.RootPanel import RootPanel 40 from pyjamas.ui.RootPanel import RootPanel
41 from pyjamas.ui.HTML import HTML 41 # from pyjamas.ui.HTML import HTML
42 from pyjamas.ui.KeyboardListener import KEY_ESCAPE 42 from pyjamas.ui.KeyboardListener import KEY_ESCAPE
43 from pyjamas.Timer import Timer 43 from pyjamas.Timer import Timer
44 from pyjamas import Window, DOM 44 from pyjamas import Window, DOM
45 45
46 from sat_browser import json 46 from sat_browser import json
67 67
68 68
69 unicode = str # FIXME: pyjamas workaround 69 unicode = str # FIXME: pyjamas workaround
70 70
71 71
72 MAX_MBLOG_CACHE = 500 # Max microblog entries kept in memories 72 # MAX_MBLOG_CACHE = 500 # Max microblog entries kept in memories # FIXME
73 73
74 74
75 class SatWebFrontend(InputHistory, QuickApp): 75 class SatWebFrontend(InputHistory, QuickApp):
76 def onModuleLoad(self): 76 def onModuleLoad(self):
77 log.info("============ onModuleLoad ==============") 77 log.info("============ onModuleLoad ==============")
355 self.plug_profiles([C.PROF_KEY_NONE]) # XXX: None was used intitially, but pyjamas bug when using variable arguments and None is the only arg. 355 self.plug_profiles([C.PROF_KEY_NONE]) # XXX: None was used intitially, but pyjamas bug when using variable arguments and None is the only arg.
356 356
357 def profilePlugged(self, dummy): 357 def profilePlugged(self, dummy):
358 self._profile_plugged = True 358 self._profile_plugged = True
359 QuickApp.profilePlugged(self, C.PROF_KEY_NONE) 359 QuickApp.profilePlugged(self, C.PROF_KEY_NONE)
360 360 # XXX: as contact_list.update() is slow and it's called a lot of time
361 microblog_widget = self.displayWidget(blog.MicroblogPanel, ()) 361 # during profile plugging, we prevent it before it's plugged
362 self.setSelected(microblog_widget) 362 # and do all at once now
363 contact_list = self.contact_list
364 contact_list.update()
365
366
367 blog_widget = self.displayWidget(blog.Blog, ())
368 self.setSelected(blog_widget)
363 369
364 # we fill the panels already here 370 # we fill the panels already here
365 for wid in self.widgets.getWidgets(blog.MicroblogPanel): 371 # for wid in self.widgets.getWidgets(blog.MicroblogPanel):
366 if wid.accept_all(): 372 # if wid.accept_all():
367 self.bridge.getMassiveMblogs('ALL', (), None, profile=C.PROF_KEY_NONE, callback=wid.massiveInsert) 373 # self.bridge.getMassiveMblogs('ALL', (), None, profile=C.PROF_KEY_NONE, callback=wid.massiveInsert)
368 else: 374 # else:
369 self.bridge.getMassiveMblogs('GROUP', list(wid.accepted_groups), None, profile=C.PROF_KEY_NONE, callback=wid.massiveInsert) 375 # self.bridge.getMassiveMblogs('GROUP', list(wid.accepted_groups), None, profile=C.PROF_KEY_NONE, callback=wid.massiveInsert)
370 376
371 #we ask for our own microblogs: 377 #we ask for our own microblogs:
372 self.loadOurMainEntries() 378 # self.loadOurMainEntries()
373 379
374 def gotDefaultMUC(default_muc): 380 def gotDefaultMUC(default_muc):
375 self.default_muc = default_muc 381 self.default_muc = default_muc
376 self.bridge.getDefaultMUC(profile=None, callback=gotDefaultMUC) 382 self.bridge.getDefaultMUC(profile=None, callback=gotDefaultMUC)
377 383
436 pass 442 pass
437 elif "xmlui" in data: 443 elif "xmlui" in data:
438 ui = xmlui.create(self, xml_data=data['xmlui']) 444 ui = xmlui.create(self, xml_data=data['xmlui'])
439 ui.show() 445 ui.show()
440 elif "public_blog" in data: 446 elif "public_blog" in data:
447 # FIXME: remove this, this is not generic !
441 # TODO: use the bare instead of node when all blogs can be retrieved 448 # TODO: use the bare instead of node when all blogs can be retrieved
442 node = jid.JID(data['public_blog']).node 449 node = jid.JID(data['public_blog']).node
443 # FIXME: "/blog/{}" won't work with unicode nodes 450 # FIXME: "/blog/{}" won't work with unicode nodes
444 self.displayWidget(widget.WebWidget, "/blog/{}".format(node), show_url=False, new_tab=_(u"{}'s blog").format(unicode(node))) 451 self.displayWidget(widget.WebWidget, "/blog/{}".format(node), show_url=False, new_tab=_(u"{}'s blog").format(unicode(node)))
445 else: 452 else:
459 """ 466 """
460 if data is None: 467 if data is None:
461 data = {} 468 data = {}
462 self.bridge.launchAction(callback_id, data, profile=profile, callback=self._actionCb, errback=self._actionEb) 469 self.bridge.launchAction(callback_id, data, profile=profile, callback=self._actionCb, errback=self._actionEb)
463 470
464 def _ownBlogsFills(self, mblogs, mblog_panel=None): 471 # def _ownBlogsFills(self, mblogs, mblog_panel=None):
465 """Put our own microblogs in cache, then fill the panels with them. 472 # """Put our own microblogs in cache, then fill the panels with them.
466 473
467 @param mblogs (dict): dictionary mapping a publisher JID to blogs data. 474 # @param mblogs (dict): dictionary mapping a publisher JID to blogs data.
468 @param mblog_panel (MicroblogPanel): the panel to fill, or all if None. 475 # @param mblog_panel (MicroblogPanel): the panel to fill, or all if None.
469 """ 476 # """
470 cache = [] 477 # cache = []
471 for publisher in mblogs: 478 # for publisher in mblogs:
472 for mblog in mblogs[publisher][0]: 479 # for mblog in mblogs[publisher][0]:
473 if 'content' not in mblog: 480 # if 'content' not in mblog:
474 log.warning(u"No content found in microblog [%s]" % mblog) 481 # log.warning(u"No content found in microblog [%s]" % mblog)
475 continue 482 # continue
476 if 'groups' in mblog: 483 # if 'groups' in mblog:
477 _groups = set(mblog['groups'].split() if mblog['groups'] else []) 484 # _groups = set(mblog['groups'].split() if mblog['groups'] else [])
478 else: 485 # else:
479 _groups = None 486 # _groups = None
480 mblog_entry = blog.MicroblogItem(mblog) 487 # mblog_entry = blog.MicroblogItem(mblog)
481 cache.append((_groups, mblog_entry)) 488 # cache.append((_groups, mblog_entry))
482 489
483 self.mblog_cache.extend(cache) 490 # self.mblog_cache.extend(cache)
484 if len(self.mblog_cache) > MAX_MBLOG_CACHE: 491 # if len(self.mblog_cache) > MAX_MBLOG_CACHE:
485 del self.mblog_cache[0:len(self.mblog_cache - MAX_MBLOG_CACHE)] 492 # del self.mblog_cache[0:len(self.mblog_cache - MAX_MBLOG_CACHE)]
486 493
487 widget_list = [mblog_panel] if mblog_panel else self.widgets.getWidgets(blog.MicroblogPanel) 494 # widget_list = [mblog_panel] if mblog_panel else self.widgets.getWidgets(blog.MicroblogPanel)
488 495
489 for wid in widget_list: 496 # for wid in widget_list:
490 self.fillMicroblogPanel(wid, cache) 497 # self.fillMicroblogPanel(wid, cache)
491 498
492 # FIXME 499 # # FIXME
493 500
494 if self.initialised: 501 # if self.initialised:
495 return 502 # return
496 self.initialised = True # initialisation phase is finished here 503 # self.initialised = True # initialisation phase is finished here
497 for event_data in self.init_cache: # so we have to send all the cached events 504 # for event_data in self.init_cache: # so we have to send all the cached events
498 self.personalEventHandler(*event_data) 505 # self.personalEventHandler(*event_data)
499 del self.init_cache 506 # del self.init_cache
500 507
501 def loadOurMainEntries(self, index=0, mblog_panel=None): 508 # def loadOurMainEntries(self, index=0, mblog_panel=None):
502 """Load a page of our own blogs from the cache or ask them to the 509 # """Load a page of our own blogs from the cache or ask them to the
503 backend. Then fill the panels with them. 510 # backend. Then fill the panels with them.
504 511
505 @param index (int): starting index of the blog page to retrieve. 512 # @param index (int): starting index of the blog page to retrieve.
506 @param mblog_panel (MicroblogPanel): the panel to fill, or all if None. 513 # @param mblog_panel (MicroblogPanel): the panel to fill, or all if None.
507 """ 514 # """
508 delta = index - self.next_rsm_index 515 # delta = index - self.next_rsm_index
509 if delta < 0: 516 # if delta < 0:
510 assert mblog_panel is not None 517 # assert mblog_panel is not None
511 self.fillMicroblogPanel(mblog_panel, self.mblog_cache[index:index + C.RSM_MAX_ITEMS]) 518 # self.fillMicroblogPanel(mblog_panel, self.mblog_cache[index:index + C.RSM_MAX_ITEMS])
512 return 519 # return
513 520
514 def cb(result): 521 # def cb(result):
515 self._ownBlogsFills(result, mblog_panel) 522 # self._ownBlogsFills(result, mblog_panel)
516 523
517 rsm = {'max_': str(delta + C.RSM_MAX_ITEMS), 'index': str(self.next_rsm_index)} 524 # rsm = {'max_': str(delta + C.RSM_MAX_ITEMS), 'index': str(self.next_rsm_index)}
518 self.bridge.getMassiveMblogs('JID', [unicode(self.whoami.bare)], rsm, callback=cb, profile=C.PROF_KEY_NONE) 525 # self.bridge.getMassiveMblogs('JID', [unicode(self.whoami.bare)], rsm, callback=cb, profile=C.PROF_KEY_NONE)
519 self.next_rsm_index = index + C.RSM_MAX_ITEMS 526 # self.next_rsm_index = index + C.RSM_MAX_ITEMS
520 527
521 ## Signals callbacks ## 528 ## Signals callbacks ##
522 529
523 def personalEventHandler(self, sender, event_type, data): 530 # def personalEventHandler(self, sender, event_type, data):
524 # FIXME: move some code from here to QuickApp 531 # elif event_type == 'MICROBLOG_DELETE':
525 if not self.initialised: 532 # for wid in self.widgets.getWidgets(blog.MicroblogPanel):
526 self.init_cache.append((sender, event_type, data)) 533 # wid.removeEntry(data['type'], data['id'])
527 return 534
528 sender = jid.JID(sender).bare 535 # if sender == self.whoami.bare and data['type'] == 'main_item':
529 if event_type == "MICROBLOG": 536 # for index in xrange(0, len(self.mblog_cache)):
530 if not 'content' in data: 537 # entry = self.mblog_cache[index]
531 log.warning("No content found in microblog data") 538 # if entry[1].id == data['id']:
532 return 539 # self.mblog_cache.remove(entry)
533 if 'groups' in data: 540 # break
534 _groups = set(data['groups'].split() if data['groups'] else []) 541
535 else: 542 # def fillMicroblogPanel(self, mblog_panel, mblogs):
536 _groups = None 543 # """Fill a microblog panel with entries in cache
537 mblog_entry = blog.MicroblogItem(data) 544
538 545 # @param mblog_panel: MicroblogPanel instance
539 for wid in self.widgets.getWidgets(blog.MicroblogPanel): 546 # """
540 wid.addEntryIfAccepted(sender, _groups, mblog_entry) 547 # #XXX: only our own entries are cached
541 548 # for cache_entry in mblogs:
542 if sender == self.whoami.bare: 549 # _groups, mblog_entry = cache_entry
543 found = False 550 # mblog_panel.addEntryIfAccepted(self.whoami.bare, *cache_entry)
544 for index in xrange(0, len(self.mblog_cache)): 551
545 entry = self.mblog_cache[index] 552 # def getEntityMBlog(self, entity):
546 if entry[1].id == mblog_entry.id: 553 # # FIXME: call this after a contact has been added to roster
547 # replace existing entry 554 # log.info(u"geting mblog for entity [%s]" % (entity,))
548 self.mblog_cache.remove(entry) 555 # for lib_wid in self.libervia_widgets:
549 self.mblog_cache.insert(index, (_groups, mblog_entry)) 556 # if isinstance(lib_wid, blog.MicroblogPanel):
550 found = True 557 # if lib_wid.isJidAccepted(entity):
551 break 558 # self.bridge.call('getMassiveMblogs', lib_wid.massiveInsert, 'JID', [unicode(entity)])
552 if not found:
553 self.mblog_cache.append((_groups, mblog_entry))
554 if len(self.mblog_cache) > MAX_MBLOG_CACHE:
555 del self.mblog_cache[0:len(self.mblog_cache - MAX_MBLOG_CACHE)]
556 elif event_type == 'MICROBLOG_DELETE':
557 for wid in self.widgets.getWidgets(blog.MicroblogPanel):
558 wid.removeEntry(data['type'], data['id'])
559
560 if sender == self.whoami.bare and data['type'] == 'main_item':
561 for index in xrange(0, len(self.mblog_cache)):
562 entry = self.mblog_cache[index]
563 if entry[1].id == data['id']:
564 self.mblog_cache.remove(entry)
565 break
566
567 def fillMicroblogPanel(self, mblog_panel, mblogs):
568 """Fill a microblog panel with entries in cache
569
570 @param mblog_panel: MicroblogPanel instance
571 """
572 #XXX: only our own entries are cached
573 for cache_entry in mblogs:
574 _groups, mblog_entry = cache_entry
575 mblog_panel.addEntryIfAccepted(self.whoami.bare, *cache_entry)
576
577 def getEntityMBlog(self, entity):
578 # FIXME: call this after a contact has been added to roster
579 log.info(u"geting mblog for entity [%s]" % (entity,))
580 for lib_wid in self.libervia_widgets:
581 if isinstance(lib_wid, blog.MicroblogPanel):
582 if lib_wid.isJidAccepted(entity):
583 self.bridge.call('getMassiveMblogs', lib_wid.massiveInsert, 'JID', [unicode(entity)])
584 559
585 def displayWidget(self, class_, target, dropped=False, new_tab=None, *args, **kwargs): 560 def displayWidget(self, class_, target, dropped=False, new_tab=None, *args, **kwargs):
586 """Get or create a LiberviaWidget and select it. When the user dropped 561 """Get or create a LiberviaWidget and select it. When the user dropped
587 something, a new widget is always created, otherwise we look for an 562 something, a new widget is always created, otherwise we look for an
588 existing widget and re-use it if it's in the current tab. 563 existing widget and re-use it if it's in the current tab.