Mercurial > libervia-desktop-kivy
comparison cagou/plugins/plugin_wid_chat.py @ 325:5868a5575e01
chat: cleaning + some improvments:
- code cleaning, removed some dead code
- some improvments on the way size is calculated, removed unnecessary sizing methods which
were linked to properties
- image have now a max size, this avoid gigantic image in the whole screen
- in SimpleXHTMLWidget, Label are now splitted when xhtml is set
- use a DelayedBoxLayout for messages, as they are really slow to be resized
- use of RecycleView has been investigated, but it is not currently usable as dynamic
contents are not propertly handled (see https://github.com/kivy/kivy/issues/6580 and
https://github.com/kivy/kivy/issues/6582). Furthermore, some tests with RecycleView on
Android don't give the expected speed boost, so BoxLayout still seems like the way to go
for the moment. To be re-investigated at a later point if necessary.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 06 Dec 2019 13:25:31 +0100 |
parents | e2b51663d8b8 |
children | d9d2b56f46db |
comparison
equal
deleted
inserted
replaced
324:4374cb741eb5 | 325:5868a5575e01 |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | 2 |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | 3 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client |
5 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) | 4 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 5 |
7 # This program is free software: you can redistribute it and/or modify | 6 # This program is free software: you can redistribute it and/or modify |
19 | 18 |
20 | 19 |
21 from functools import partial | 20 from functools import partial |
22 import mimetypes | 21 import mimetypes |
23 import sys | 22 import sys |
24 from sat.core import log as logging | |
25 from sat.core.i18n import _ | |
26 from sat.core import exceptions | |
27 from cagou.core.constants import Const as C | |
28 from kivy.uix.boxlayout import BoxLayout | 23 from kivy.uix.boxlayout import BoxLayout |
29 from kivy.uix.gridlayout import GridLayout | |
30 from kivy.uix.textinput import TextInput | 24 from kivy.uix.textinput import TextInput |
31 from kivy.metrics import sp, dp | 25 from kivy.metrics import sp, dp |
32 from kivy.clock import Clock | 26 from kivy.clock import Clock |
33 from kivy import properties | 27 from kivy import properties |
28 from kivy.uix.dropdown import DropDown | |
29 from kivy.core.window import Window | |
30 from sat.core import log as logging | |
31 from sat.core.i18n import _ | |
32 from sat.core import exceptions | |
34 from sat_frontends.quick_frontend import quick_widgets | 33 from sat_frontends.quick_frontend import quick_widgets |
35 from sat_frontends.quick_frontend import quick_chat | 34 from sat_frontends.quick_frontend import quick_chat |
36 from sat_frontends.tools import jid | 35 from sat_frontends.tools import jid |
36 from cagou import G | |
37 from cagou.core.constants import Const as C | |
37 from cagou.core import cagou_widget | 38 from cagou.core import cagou_widget |
38 from cagou.core import xmlui | 39 from cagou.core import xmlui |
39 from cagou.core.image import Image | 40 from cagou.core.image import Image |
40 from cagou.core.common import SymbolButton, JidButton | 41 from cagou.core.common import SymbolButton, JidButton |
41 from kivy.uix.dropdown import DropDown | |
42 from kivy.core.window import Window | |
43 from cagou import G | |
44 from cagou.core import menu | 42 from cagou.core import menu |
43 # from random import randrange | |
45 | 44 |
46 log = logging.getLogger(__name__) | 45 log = logging.getLogger(__name__) |
47 | 46 |
48 PLUGIN_INFO = { | 47 PLUGIN_INFO = { |
49 "name": _("chat"), | 48 "name": _("chat"), |
71 | 70 |
72 class MessAvatar(Image): | 71 class MessAvatar(Image): |
73 pass | 72 pass |
74 | 73 |
75 | 74 |
76 class MessageWidget(BoxLayout, quick_chat.MessageWidget): | 75 class MessageWidget(quick_chat.MessageWidget, BoxLayout): |
77 mess_data = properties.ObjectProperty() | 76 mess_data = properties.ObjectProperty() |
78 mess_xhtml = properties.ObjectProperty() | 77 mess_xhtml = properties.ObjectProperty() |
79 mess_padding = (dp(5), dp(5)) | 78 mess_padding = (dp(5), dp(5)) |
80 avatar = properties.ObjectProperty() | 79 avatar = properties.ObjectProperty() |
81 delivery = properties.ObjectProperty() | 80 delivery = properties.ObjectProperty() |
82 font_size = properties.NumericProperty(sp(12)) | 81 font_size = properties.NumericProperty(sp(12)) |
83 | 82 right_part = properties.ObjectProperty() |
84 def __init__(self, **kwargs): | 83 header_box = properties.ObjectProperty() |
85 # self must be registered in widgets before kv is parsed | 84 |
86 kwargs['mess_data'].widgets.add(self) | 85 def on_mess_data(self, wid, mess_data): |
87 super(MessageWidget, self).__init__(**kwargs) | 86 mess_data.widgets.add(self) |
88 avatar_path = self.mess_data.avatar | |
89 if avatar_path is not None: | |
90 self.avatar.source = avatar_path | |
91 | 87 |
92 @property | 88 @property |
93 def chat(self): | 89 def chat(self): |
94 """return parent Chat instance""" | 90 """return parent Chat instance""" |
95 return self.mess_data.parent | 91 return self.mess_data.parent |
96 | 92 |
93 def _get_from_mess_data(self, name, default): | |
94 if self.mess_data is None: | |
95 return default | |
96 return getattr(self.mess_data, name) | |
97 | |
97 def _get_message(self): | 98 def _get_message(self): |
98 """Return currently displayed message""" | 99 """Return currently displayed message""" |
100 if self.mess_data is None: | |
101 return "" | |
99 return self.mess_data.main_message | 102 return self.mess_data.main_message |
100 | 103 |
101 def _set_message(self, message): | 104 def _set_message(self, message): |
105 if self.mess_data is None: | |
106 return False | |
102 if message == self.mess_data.message.get(""): | 107 if message == self.mess_data.message.get(""): |
103 return False | 108 return False |
104 self.mess_data.message = {"": message} | 109 self.mess_data.message = {"": message} |
105 return True | 110 return True |
106 | 111 |
107 message = properties.AliasProperty(_get_message, _set_message) | 112 message = properties.AliasProperty( |
108 | 113 partial(_get_from_mess_data, name="main_message", default=""), |
109 @property | 114 _set_message, |
110 def message_xhtml(self): | 115 bind=['mess_data'], |
111 """Return currently displayed message""" | 116 ) |
112 return self.mess_data.main_message_xhtml | 117 message_xhtml = properties.AliasProperty( |
118 partial(_get_from_mess_data, name="main_message_xhtml", default=""), | |
119 bind=['mess_data']) | |
120 mess_type = properties.AliasProperty( | |
121 partial(_get_from_mess_data, name="type", default=""), bind=['mess_data']) | |
122 own_mess = properties.AliasProperty( | |
123 partial(_get_from_mess_data, name="own_mess", default=False), bind=['mess_data']) | |
124 nick = properties.AliasProperty( | |
125 partial(_get_from_mess_data, name="nick", default=""), bind=['mess_data']) | |
126 time_text = properties.AliasProperty( | |
127 partial(_get_from_mess_data, name="time_text", default=""), bind=['mess_data']) | |
113 | 128 |
114 @property | 129 @property |
115 def info_type(self): | 130 def info_type(self): |
116 return self.mess_data.info_type | 131 return self.mess_data.info_type |
117 | |
118 def widthAdjust(self): | |
119 """this widget grows up with its children""" | |
120 pass | |
121 # parent = self.mess_xhtml.parent | |
122 # padding_x = self.mess_padding[0] | |
123 # text_width, text_height = self.mess_xhtml.texture_size | |
124 # if text_width > parent.width: | |
125 # self.mess_xhtml.text_size = (parent.width - padding_x, None) | |
126 # self.text_max = text_width | |
127 # elif self.mess_xhtml.text_size[0] is not None and text_width < parent.width - padding_x: | |
128 # if text_width < self.text_max: | |
129 # self.mess_xhtml.text_size = (None, None) | |
130 # else: | |
131 # self.mess_xhtml.text_size = (parent.width - padding_x, None) | |
132 | 132 |
133 def update(self, update_dict): | 133 def update(self, update_dict): |
134 if 'avatar' in update_dict: | 134 if 'avatar' in update_dict: |
135 self.avatar.source = update_dict['avatar'] | 135 self.avatar.source = update_dict['avatar'] |
136 if 'status' in update_dict: | 136 if 'status' in update_dict: |
171 return super(MessageInputWidget, self).keyboard_on_key_down( | 171 return super(MessageInputWidget, self).keyboard_on_key_down( |
172 window, keycode, text, modifiers) | 172 window, keycode, text, modifiers) |
173 | 173 |
174 def send_text(self): | 174 def send_text(self): |
175 self.dispatch('on_text_validate') | 175 self.dispatch('on_text_validate') |
176 | |
177 | |
178 class MessagesWidget(GridLayout): | |
179 pass | |
180 | 176 |
181 | 177 |
182 class TransferButton(SymbolButton): | 178 class TransferButton(SymbolButton): |
183 chat = properties.ObjectProperty() | 179 chat = properties.ObjectProperty() |
184 | 180 |
424 self.encryption_btn = EncryptionMainButton(self) | 420 self.encryption_btn = EncryptionMainButton(self) |
425 self.headerInputAddExtra(self.encryption_btn) | 421 self.headerInputAddExtra(self.encryption_btn) |
426 self.extra_menu = ExtraMenu(chat=self) | 422 self.extra_menu = ExtraMenu(chat=self) |
427 extra_btn = ExtraButton(chat=self) | 423 extra_btn = ExtraButton(chat=self) |
428 self.headerInputAddExtra(extra_btn) | 424 self.headerInputAddExtra(extra_btn) |
429 self.header_input.hint_text = "{}".format(target) | 425 self.header_input.hint_text = target |
430 self.postInit() | 426 Clock.schedule_once(lambda dt: self.postInit(), 0) |
431 | 427 |
432 def __str__(self): | 428 def __str__(self): |
433 return "Chat({})".format(self.target) | 429 return "Chat({})".format(self.target) |
434 | 430 |
435 def __repr__(self): | 431 def __repr__(self): |