comparison cagou/plugins/plugin_wid_chat.py @ 425:13884aac1220

chat: show images in attachments: - if an image is received from somebody in roster, it is automatically displayed (we display only for people in roster to avoid IP address leak) - encrypted files are decrypted and stored in cache before being displayed - GIFs image are shown as attachment because they are badly handle in Kivy (images frequencies is not handled correctly, and memory consumption explode). Instead, a click on it will open the GIF in the appropriate software of the platform. - a click on an attachment image will open it in the gallery
author Goffi <goffi@goffi.org>
date Wed, 26 Feb 2020 16:47:39 +0100
parents 8a9bfe3fb9c6
children d3a6ae859556
comparison
equal deleted inserted replaced
424:027fad764864 425:13884aac1220
19 19
20 from functools import partial 20 from functools import partial
21 from pathlib import Path 21 from pathlib import Path
22 import sys 22 import sys
23 import uuid 23 import uuid
24 from urllib.parse import urlparse
24 from kivy.uix.boxlayout import BoxLayout 25 from kivy.uix.boxlayout import BoxLayout
25 from kivy.uix.textinput import TextInput 26 from kivy.uix.textinput import TextInput
26 from kivy.uix.screenmanager import Screen, NoTransition 27 from kivy.uix.screenmanager import Screen, NoTransition
27 from kivy.uix import screenmanager 28 from kivy.uix import screenmanager
28 from kivy.uix.behaviors import ButtonBehavior 29 from kivy.uix.behaviors import ButtonBehavior
42 from cagou import G 43 from cagou import G
43 from ..core.constants import Const as C 44 from ..core.constants import Const as C
44 from ..core import cagou_widget 45 from ..core import cagou_widget
45 from ..core import xmlui 46 from ..core import xmlui
46 from ..core.image import Image 47 from ..core.image import Image
47 from ..core.common import SymbolButton, JidButton 48 from ..core.common import SymbolButton, JidButton, ContactButton
48 from ..core.behaviors import FilterBehavior 49 from ..core.behaviors import FilterBehavior
49 from ..core import menu 50 from ..core import menu
50 from ..core.common import ContactButton 51 from ..core.common_widgets import ImagesGallery
51 52
52 log = logging.getLogger(__name__) 53 log = logging.getLogger(__name__)
53 54
54 PLUGIN_INFO = { 55 PLUGIN_INFO = {
55 "name": _("chat"), 56 "name": _("chat"),
92 class AttachmentsToSend(BoxLayout): 93 class AttachmentsToSend(BoxLayout):
93 """Layout for attachments to be sent with current message""" 94 """Layout for attachments to be sent with current message"""
94 attachments = properties.ObjectProperty() 95 attachments = properties.ObjectProperty()
95 96
96 97
97 class AttachmentItem(BoxLayout): 98 class BaseAttachmentItem(BoxLayout):
98 data = properties.DictProperty() 99 data = properties.DictProperty()
99 progress = properties.NumericProperty(0) 100 progress = properties.NumericProperty(0)
101
102
103 class AttachmentItem(BaseAttachmentItem):
100 104
101 def get_symbol(self, data): 105 def get_symbol(self, data):
102 media_type = data.get(C.MESS_KEY_MEDIA_TYPE, '') 106 media_type = data.get(C.MESS_KEY_MEDIA_TYPE, '')
103 main_type = media_type.split('/', 1)[0] 107 main_type = media_type.split('/', 1)[0]
104 if main_type == 'image': 108 if main_type == 'image':
114 url = self.data.get('url') 118 url = self.data.get('url')
115 if url: 119 if url:
116 G.local_platform.open_url(url, self) 120 G.local_platform.open_url(url, self)
117 else: 121 else:
118 log.warning(f"can't find URL in {self.data}") 122 log.warning(f"can't find URL in {self.data}")
123
124
125 class AttachmentImageItem(ButtonBehavior, BaseAttachmentItem):
126 image = properties.ObjectProperty()
127
128 def on_press(self):
129 gallery = ImagesGallery(sources=[self.image.source])
130 G.host.showExtraUI(gallery)
119 131
120 132
121 class AttachmentToSendItem(AttachmentItem): 133 class AttachmentToSendItem(AttachmentItem):
122 # True when the item is being sent 134 # True when the item is being sent
123 sending = properties.BooleanProperty(False) 135 sending = properties.BooleanProperty(False)
195 self.avatar.source = update_dict['avatar'] 207 self.avatar.source = update_dict['avatar']
196 if 'status' in update_dict: 208 if 'status' in update_dict:
197 status = update_dict['status'] 209 status = update_dict['status']
198 self.delivery.text = '\u2714' if status == 'delivered' else '' 210 self.delivery.text = '\u2714' if status == 'delivered' else ''
199 211
212 def _setPath(self, item, path):
213 """Set path of decrypted file to an item"""
214 item.data['path'] = path
215
200 def add_attachments(self): 216 def add_attachments(self):
201 """Add attachments layout + attachments item""" 217 """Add attachments layout + attachments item"""
202 attachments = self.mess_data.attachments 218 attachments = self.mess_data.attachments
203 if not attachments: 219 if not attachments:
204 return 220 return
205 root_layout = AttachmentsLayout() 221 root_layout = AttachmentsLayout()
206 self.right_part.add_widget(root_layout) 222 self.right_part.add_widget(root_layout)
207 layout = root_layout.attachments 223 layout = root_layout.attachments
208 for attachment in attachments: 224 for attachment in attachments:
209 item = AttachmentItem(data=attachment) 225 media_type = attachment.get(C.MESS_KEY_MEDIA_TYPE, '')
226 main_type = media_type.split('/', 1)[0]
227 if ((main_type == 'image'
228 # GIF images are really badly handled by Kivy, the
229 # memory consumption explode, and the images frequencies
230 # are not handled correctly, thus we can't display them
231 # and user will have to open the item.
232 and media_type != "image/gif"
233 and (self.mess_data.own_mess or self.chat.contact_list.isInRoster(
234 self.mess_data.from_jid)))):
235 url = urlparse(attachment['url'])
236 if url.scheme == "aesgcm":
237 # we remove the URL now, we'll replace it by
238 # the local decrypted version
239 del attachment['url']
240 item = AttachmentImageItem(data=attachment)
241 G.host.downloadURL(
242 url.geturl(),
243 callback=partial(self._setPath, item),
244 dest=C.FILE_DEST_CACHE,
245 profile=self.chat.profile,
246 )
247 else:
248 item = AttachmentImageItem(data=attachment)
249 else:
250 item = AttachmentItem(data=attachment)
210 layout.add_widget(item) 251 layout.add_widget(item)
211 252
212 253
213 class MessageInputBox(BoxLayout): 254 class MessageInputBox(BoxLayout):
214 message_input = properties.ObjectProperty() 255 message_input = properties.ObjectProperty()