1
1
import re
2
2
import unicodedata
3
3
from collections import OrderedDict , defaultdict
4
- from datetime import date , datetime
4
+ from datetime import date , datetime , timedelta
5
5
from sys import platform
6
- from time import ctime , time
6
+ from time import ctime , sleep , time
7
7
from typing import Any , Callable , Dict , List , Optional , Tuple , Union
8
8
from urllib .parse import urljoin , urlparse
9
9
22
22
STREAM_TOPIC_SEPARATOR , TIME_MENTION_MARKER ,
23
23
)
24
24
from zulipterminal .helper import (
25
- Message , format_string , match_emoji , match_group , match_stream ,
25
+ Message , asynch , format_string , match_emoji , match_group , match_stream ,
26
26
match_topics , match_user ,
27
27
)
28
28
from zulipterminal .ui_tools .buttons import EditModeButton
@@ -40,6 +40,8 @@ def __init__(self, view: Any) -> None:
40
40
self .stream_id = None # type: Optional[int]
41
41
self .recipient_user_ids = [] # type: List[int]
42
42
self .msg_body_edit_enabled = True
43
+ self .send_next_typing_update = datetime .now ()
44
+ self .last_key_update = datetime .now ()
43
45
self .FOCUS_CONTAINER_HEADER = 0
44
46
self .FOCUS_HEADER_BOX_RECIPIENT = 0
45
47
self .FOCUS_HEADER_BOX_STREAM = 0
@@ -57,13 +59,19 @@ def main_view(self, new: bool) -> Any:
57
59
def set_editor_mode (self ) -> None :
58
60
self .view .controller .enter_editor_mode_with (self )
59
61
62
+ def send_stop_typing_status (self ) -> None :
63
+ self .model .send_typing_status_by_user_ids (self .recipient_user_ids ,
64
+ status = 'stop' )
65
+ self .send_next_typing_update = datetime .now ()
66
+
60
67
def private_box_view (self , button : Any = None , email : str = '' ,
61
68
recipient_user_ids : Optional [List [int ]]= None ) -> None :
62
69
self .set_editor_mode ()
63
70
if recipient_user_ids :
64
71
self .recipient_user_ids = recipient_user_ids
65
72
if email == '' and button is not None :
66
73
email = button .email
74
+ self .send_next_typing_update = datetime .now ()
67
75
self .to_write_box = ReadlineEdit ("To: " , edit_text = email )
68
76
self .msg_write_box = ReadlineEdit (multiline = True )
69
77
self .msg_write_box .enable_autocomplete (
@@ -83,6 +91,33 @@ def private_box_view(self, button: Any=None, email: str='',
83
91
]
84
92
self .focus_position = self .FOCUS_CONTAINER_MESSAGE
85
93
94
+ # Typing status is sent in regular intervals to limit the number of
95
+ # notifications sent. Idleness should also prompt a notification.
96
+ # Refer to https://zulip.com/api/set-typing-status for the protocol
97
+ # on typing notifications sent by clients.
98
+ TYPING_STARTED_WAIT_PERIOD = 10
99
+ TYPING_STOPPED_WAIT_PERIOD = 5
100
+
101
+ start_period_delta = timedelta (seconds = TYPING_STARTED_WAIT_PERIOD )
102
+ stop_period_delta = timedelta (seconds = TYPING_STOPPED_WAIT_PERIOD )
103
+
104
+ def on_type_send_status (edit : object , new_edit_text : str ) -> None :
105
+ if new_edit_text :
106
+ self .last_key_update = datetime .now ()
107
+ if self .last_key_update > self .send_next_typing_update :
108
+ self .model .send_typing_status_by_user_ids (
109
+ self .recipient_user_ids , status = 'start' )
110
+ self .send_next_typing_update += start_period_delta
111
+
112
+ @asynch
113
+ def on_idle_send_status (* args : object ) -> None :
114
+ sleep (TYPING_STOPPED_WAIT_PERIOD )
115
+ if datetime .now () > self .last_key_update + stop_period_delta :
116
+ self .send_stop_typing_status ()
117
+
118
+ urwid .connect_signal (self .msg_write_box , 'change' , on_type_send_status )
119
+ urwid .connect_signal (self .msg_write_box , 'change' , on_idle_send_status )
120
+
86
121
def stream_box_view (self , stream_id : int , caption : str = '' , title : str = '' ,
87
122
) -> None :
88
123
self .set_editor_mode ()
@@ -343,6 +378,7 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
343
378
content = self .msg_write_box .edit_text
344
379
)
345
380
else :
381
+ self .send_stop_typing_status ()
346
382
if self .msg_edit_id :
347
383
success = self .model .update_private_message (
348
384
content = self .msg_write_box .edit_text ,
@@ -355,12 +391,14 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
355
391
)
356
392
if success :
357
393
self .msg_write_box .edit_text = ''
394
+ self .send_stop_typing_status ()
358
395
if self .msg_edit_id :
359
396
self .msg_edit_id = None
360
397
self .keypress (size , 'esc' )
361
398
elif is_command_key ('GO_BACK' , key ):
362
399
self .msg_edit_id = None
363
400
self .msg_body_edit_enabled = True
401
+ self .send_stop_typing_status ()
364
402
self .view .controller .exit_editor_mode ()
365
403
self .main_view (False )
366
404
self .view .middle_column .set_focus ('body' )
0 commit comments