comparison src/cagou/plugins/plugin_wid_chat.py @ 78:46d962910801

chat: file upload first draft: - added a icon to upload files - only do a basic upload with list file browser for now - use the new progressFinished and progressError listeners
author Goffi <goffi@goffi.org>
date Thu, 22 Dec 2016 19:03:06 +0100
parents 4a1e1012337e
children c711be670ecd
comparison
equal deleted inserted replaced
77:bc170ccca744 78:46d962910801
20 20
21 from sat.core import log as logging 21 from sat.core import log as logging
22 log = logging.getLogger(__name__) 22 log = logging.getLogger(__name__)
23 from sat.core.i18n import _ 23 from sat.core.i18n import _
24 from cagou.core.constants import Const as C 24 from cagou.core.constants import Const as C
25 from kivy.uix.boxlayout import BoxLayout
25 from kivy.uix.gridlayout import GridLayout 26 from kivy.uix.gridlayout import GridLayout
26 from kivy.uix.stacklayout import StackLayout 27 from kivy.uix.stacklayout import StackLayout
27 from kivy.uix.scrollview import ScrollView 28 from kivy.uix.scrollview import ScrollView
28 from kivy.uix.textinput import TextInput 29 from kivy.uix.textinput import TextInput
29 from kivy.uix.label import Label 30 from kivy.uix.label import Label
527 def update(self, update_dict): 528 def update(self, update_dict):
528 if 'avatar' in update_dict: 529 if 'avatar' in update_dict:
529 self.avatar.source = update_dict['avatar'] 530 self.avatar.source = update_dict['avatar']
530 531
531 532
533 class MessageInputBox(BoxLayout):
534 pass
535
536
532 class MessageInputWidget(TextInput): 537 class MessageInputWidget(TextInput):
533 538
534 def _key_down(self, key, repeat=False): 539 def _key_down(self, key, repeat=False):
535 displayed_str, internal_str, internal_action, scale = key 540 displayed_str, internal_str, internal_action, scale = key
536 if internal_action == 'enter': 541 if internal_action == 'enter':
541 546
542 class MessagesWidget(GridLayout): 547 class MessagesWidget(GridLayout):
543 pass 548 pass
544 549
545 550
551 class FileUploader(BoxLayout):
552
553 def __init__(self, parent_chat, **kwargs):
554 self.parent_chat = parent_chat
555 super(FileUploader, self).__init__(orientation='vertical', **kwargs)
556
557
546 class Chat(quick_chat.QuickChat, cagou_widget.CagouWidget): 558 class Chat(quick_chat.QuickChat, cagou_widget.CagouWidget):
559 message_input = properties.ObjectProperty()
547 560
548 def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, subject=None, profiles=None): 561 def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, subject=None, profiles=None):
549 quick_chat.QuickChat.__init__(self, host, target, type_, nick, occupants, subject, profiles=profiles) 562 quick_chat.QuickChat.__init__(self, host, target, type_, nick, occupants, subject, profiles=profiles)
550 cagou_widget.CagouWidget.__init__(self) 563 cagou_widget.CagouWidget.__init__(self)
551 self.header_input.hint_text = u"{}".format(target) 564 self.header_input.hint_text = u"{}".format(target)
552 scroll_view = ScrollView(size_hint=(1,0.8), scroll_y=0, do_scroll_x=False) 565 scroll_view = ScrollView(size_hint=(1,0.8), scroll_y=0, do_scroll_x=False)
553 self.messages_widget = MessagesWidget() 566 self.messages_widget = MessagesWidget()
554 scroll_view.add_widget(self.messages_widget) 567 scroll_view.add_widget(self.messages_widget)
555 self.add_widget(scroll_view) 568 self.add_widget(scroll_view)
556 message_input = MessageInputWidget() 569 self.add_widget(MessageInputBox())
557 message_input.bind(on_text_validate=self.onSend) 570 self.host.addListener('progressError', self.onProgressError, profiles)
558 self.add_widget(message_input) 571 self.host.addListener('progressFinished', self.onProgressFinished, profiles)
572 self._waiting_pids = {} # waiting progress ids
559 self.postInit() 573 self.postInit()
560 574
561 @classmethod 575 @classmethod
562 def factory(cls, plugin_info, target, profiles): 576 def factory(cls, plugin_info, target, profiles):
563 profiles = list(profiles) 577 profiles = list(profiles)
590 mess_type = C.MESS_TYPE_GROUPCHAT if self.type == C.CHAT_GROUP else C.MESS_TYPE_CHAT, # TODO: put this in QuickChat 604 mess_type = C.MESS_TYPE_GROUPCHAT if self.type == C.CHAT_GROUP else C.MESS_TYPE_CHAT, # TODO: put this in QuickChat
591 profile_key=self.profile 605 profile_key=self.profile
592 ) 606 )
593 input_widget.text = '' 607 input_widget.text = ''
594 608
609 def onProgressFinished(self, progress_id, metadata, profile):
610 try:
611 callback = self._waiting_pids.pop(progress_id)
612 except KeyError:
613 return
614 callback(metadata, profile)
615
616 def onProgressError(self, progress_id, err_msg, profile):
617 try:
618 del self._waiting_pids[progress_id]
619 except KeyError:
620 return
621 # TODO: display message to user
622 log.warning(u"Can't upload file: {}".format(err_msg))
623
624 def onUploadButton(self):
625 G.host.showExtraUI(FileUploader(self))
626
627 def fileUploadDone(self, metadata, profile):
628 log.debug("file uploaded: {}".format(metadata))
629 G.host.messageSend(
630 self.target,
631 {'': metadata['url']},
632 mess_type = C.MESS_TYPE_GROUPCHAT if self.type == C.CHAT_GROUP else C.MESS_TYPE_CHAT,
633 profile_key=profile
634 )
635
636 def fileUploadCb(self, progress_data):
637 try:
638 progress_id = progress_data['progress']
639 except KeyError:
640 xmlui = progress_data['xmlui']
641 G.host.showUI(xmlui)
642 else:
643 self._waiting_pids[progress_id] = self.fileUploadDone
644
645 def onUploadOK(self, file_chooser):
646 if file_chooser.selection:
647 file_path = file_chooser.selection[0]
648 G.host.bridge.fileUpload(
649 file_path,
650 "",
651 "",
652 {"ignore_tls_errors": C.BOOL_TRUE}, # FIXME: should not be the default
653 self.profile,
654 callback = self.fileUploadCb
655 )
656 G.host.closeUI()
657
658 def onUploadCancel(self, file_chooser):
659 G.host.closeUI()
660
595 def _mucJoinCb(self, joined_data): 661 def _mucJoinCb(self, joined_data):
596 joined, room_jid_s, occupants, user_nick, subject, profile = joined_data 662 joined, room_jid_s, occupants, user_nick, subject, profile = joined_data
597 self.host.mucRoomJoinedHandler(*joined_data[1:]) 663 self.host.mucRoomJoinedHandler(*joined_data[1:])
598 jid_ = jid.JID(room_jid_s) 664 jid_ = jid.JID(room_jid_s)
599 self.changeWidget(jid_) 665 self.changeWidget(jid_)
631 def discoEb(failure): 697 def discoEb(failure):
632 log.warning(u"Disco failure, ignore this text: {}".format(failure)) 698 log.warning(u"Disco failure, ignore this text: {}".format(failure))
633 699
634 G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb) 700 G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb)
635 701
702 def _onDelete(self):
703 self.host.removeListener('progressFinished', self.onProgressFinished)
704 self.host.removeListener('progressError', self.onProgressError)
705 return super(Chat, self).onDelete()
706
636 def onDelete(self, force=False): 707 def onDelete(self, force=False):
637 if force==True: 708 if force==True:
638 return super(Chat, self).onDelete() 709 return self._onDelete()
639 if len(list(G.host.widgets.getWidgets(self.__class__, self.target, profiles=self.profiles))) > 1: 710 if len(list(G.host.widgets.getWidgets(self.__class__, self.target, profiles=self.profiles))) > 1:
640 # we don't keep duplicate widgets 711 # we don't keep duplicate widgets
641 return super(Chat, self).onDelete() 712 return self._onDelete()
642 return False 713 return False
643 714
644 715
645 PLUGIN_INFO["factory"] = Chat.factory 716 PLUGIN_INFO["factory"] = Chat.factory
646 quick_widgets.register(quick_chat.QuickChat, Chat) 717 quick_widgets.register(quick_chat.QuickChat, Chat)