# HG changeset patch # User Goffi # Date 1482429786 -3600 # Node ID 46d9629108012424c2069b565735863aacd6fede # Parent bc170ccca7447539d73e17dcf7072591e590e25a 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 diff -r bc170ccca744 -r 46d962910801 src/cagou/core/cagou_main.py --- a/src/cagou/core/cagou_main.py Thu Dec 22 18:24:24 2016 +0100 +++ b/src/cagou/core/cagou_main.py Thu Dec 22 19:03:06 2016 +0100 @@ -170,6 +170,9 @@ # backend XMLUI (popups, forms, etc) xmlui_screen = Screen(name='xmlui') self._manager.add_widget(xmlui_screen) + # extra (file chooser, audio record, etc) + extra_screen = Screen(name='extra') + self._manager.add_widget(extra_screen) self.add_widget(self._manager) def changeWidget(self, widget, screen_name="main"): @@ -553,9 +556,15 @@ self.app.root.addNotifUI(ui) def showUI(self, ui): + """show a XMLUI""" self.app.root.changeWidget(ui, "xmlui") self.app.root.show("xmlui") + def showExtraUI(self, widget): + """show any extra widget""" + self.app.root.changeWidget(widget, "extra") + self.app.root.show("extra") + def closeUI(self): self.app.root.show() diff -r bc170ccca744 -r 46d962910801 src/cagou/plugins/plugin_wid_chat.kv --- a/src/cagou/plugins/plugin_wid_chat.kv Thu Dec 22 18:24:24 2016 +0100 +++ b/src/cagou/plugins/plugin_wid_chat.kv Thu Dec 22 19:03:06 2016 +0100 @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +#:import expanduser os.path.expanduser +#:import platform kivy.utils.platform : size_hint: None, None @@ -81,7 +83,34 @@ padding: root.mess_padding bold: True if root.mess_data.type == "info" else False -: +: size_hint: 1, None height: dp(40) - hint_text: "Enter your message here" + message_input: message_input + MessageInputWidget: + id: message_input + size_hint: 1, 1 + hint_text: "Enter your message here" + on_text_validate: root.parent.onSend(args[0]) + IconButton + # upload button + source: app.expand("{media}/icons/tango/actions/32/list-add.png") + allow_stretch: True + size_hint: None, 1 + width: max(self.texture_size[0], dp(40)) + on_release: root.parent.onUploadButton() + +: + FileChooserListView: + id: filechooser + rootpath: "/" if platform == 'android' else expanduser('~') + Button: + text: "upload" + size_hint: 1, None + height: dp(50) + on_release: root.parent_chat.onUploadOK(filechooser) + Button: + text: "cancel" + size_hint: 1, None + height: dp(50) + on_release: root.parent_chat.onUploadCancel(filechooser) diff -r bc170ccca744 -r 46d962910801 src/cagou/plugins/plugin_wid_chat.py --- a/src/cagou/plugins/plugin_wid_chat.py Thu Dec 22 18:24:24 2016 +0100 +++ b/src/cagou/plugins/plugin_wid_chat.py Thu Dec 22 19:03:06 2016 +0100 @@ -22,6 +22,7 @@ log = logging.getLogger(__name__) from sat.core.i18n import _ from cagou.core.constants import Const as C +from kivy.uix.boxlayout import BoxLayout from kivy.uix.gridlayout import GridLayout from kivy.uix.stacklayout import StackLayout from kivy.uix.scrollview import ScrollView @@ -529,6 +530,10 @@ self.avatar.source = update_dict['avatar'] +class MessageInputBox(BoxLayout): + pass + + class MessageInputWidget(TextInput): def _key_down(self, key, repeat=False): @@ -543,7 +548,15 @@ pass +class FileUploader(BoxLayout): + + def __init__(self, parent_chat, **kwargs): + self.parent_chat = parent_chat + super(FileUploader, self).__init__(orientation='vertical', **kwargs) + + class Chat(quick_chat.QuickChat, cagou_widget.CagouWidget): + message_input = properties.ObjectProperty() def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, subject=None, profiles=None): quick_chat.QuickChat.__init__(self, host, target, type_, nick, occupants, subject, profiles=profiles) @@ -553,9 +566,10 @@ self.messages_widget = MessagesWidget() scroll_view.add_widget(self.messages_widget) self.add_widget(scroll_view) - message_input = MessageInputWidget() - message_input.bind(on_text_validate=self.onSend) - self.add_widget(message_input) + self.add_widget(MessageInputBox()) + self.host.addListener('progressError', self.onProgressError, profiles) + self.host.addListener('progressFinished', self.onProgressFinished, profiles) + self._waiting_pids = {} # waiting progress ids self.postInit() @classmethod @@ -592,6 +606,58 @@ ) input_widget.text = '' + def onProgressFinished(self, progress_id, metadata, profile): + try: + callback = self._waiting_pids.pop(progress_id) + except KeyError: + return + callback(metadata, profile) + + def onProgressError(self, progress_id, err_msg, profile): + try: + del self._waiting_pids[progress_id] + except KeyError: + return + # TODO: display message to user + log.warning(u"Can't upload file: {}".format(err_msg)) + + def onUploadButton(self): + G.host.showExtraUI(FileUploader(self)) + + def fileUploadDone(self, metadata, profile): + log.debug("file uploaded: {}".format(metadata)) + G.host.messageSend( + self.target, + {'': metadata['url']}, + mess_type = C.MESS_TYPE_GROUPCHAT if self.type == C.CHAT_GROUP else C.MESS_TYPE_CHAT, + profile_key=profile + ) + + def fileUploadCb(self, progress_data): + try: + progress_id = progress_data['progress'] + except KeyError: + xmlui = progress_data['xmlui'] + G.host.showUI(xmlui) + else: + self._waiting_pids[progress_id] = self.fileUploadDone + + def onUploadOK(self, file_chooser): + if file_chooser.selection: + file_path = file_chooser.selection[0] + G.host.bridge.fileUpload( + file_path, + "", + "", + {"ignore_tls_errors": C.BOOL_TRUE}, # FIXME: should not be the default + self.profile, + callback = self.fileUploadCb + ) + G.host.closeUI() + + def onUploadCancel(self, file_chooser): + G.host.closeUI() + def _mucJoinCb(self, joined_data): joined, room_jid_s, occupants, user_nick, subject, profile = joined_data self.host.mucRoomJoinedHandler(*joined_data[1:]) @@ -633,12 +699,17 @@ G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb) + def _onDelete(self): + self.host.removeListener('progressFinished', self.onProgressFinished) + self.host.removeListener('progressError', self.onProgressError) + return super(Chat, self).onDelete() + def onDelete(self, force=False): if force==True: - return super(Chat, self).onDelete() + return self._onDelete() if len(list(G.host.widgets.getWidgets(self.__class__, self.target, profiles=self.profiles))) > 1: # we don't keep duplicate widgets - return super(Chat, self).onDelete() + return self._onDelete() return False