Skip to content

Commit ce55965

Browse files
committed
README/keys/model/ui/boxes/core: Add draft message feature.
This adds support for a minimal draft message feature, storing a single draft message. The draft is stored for each session, and server-side storage will be added later when the API endpoints are available. It functions as follows: * On pressing SAVE_AS_DRAFT(`meta s`), a popup is shown confirming whether the message should be saved as a draft. This is not permitted when the message is empty, a message is being edited, or the current message is the same as a saved draft. The pop-up is bypassed when there is no saved draft. * The saved draft can be opened for editing by using the OPEN_DRAFT(`d`) key. Test amended.
1 parent 57716eb commit ce55965

File tree

7 files changed

+69
-0
lines changed

7 files changed

+69
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ source ~/.zshenv
119119
| ----------------------------------------------------- | --------------------------------------------- |
120120
| Show/hide help menu | <kbd>?</kbd> |
121121
| Show/hide about menu | <kbd>Meta</kbd> + <kbd>?</kbd> |
122+
| Save current message as a draft | <kbd>Meta</kbd> + <kbd>s</kbd> |
123+
| Open draft message saved in this session | <kbd>d</kbd> |
122124
| Go back | <kbd>esc</kbd> |
123125
| Redraw screen | <kbd>Ctrl</kbd> + <kbd>l</kbd> |
124126
| Quit | <kbd>Ctrl</kbd> + <kbd>C</kbd> |

tests/ui_tools/test_boxes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ def test_keypress_typeahead_mode_autocomplete_key(self, mocker, write_box,
430430
expect_footer_was_reset,
431431
key):
432432
write_box.is_in_typeahead_mode = current_typeahead_mode
433+
write_box.msg_write_box = mocker.Mock()
434+
write_box.msg_write_box.edit_text = ''
433435
size = (20,)
434436

435437
write_box.keypress(size, key)

zulipterminal/config/keys.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
'excluded_from_random_tips': True,
1919
'key_category': 'general',
2020
}),
21+
('SAVE_AS_DRAFT', {
22+
'keys': {'meta s'},
23+
'help_text': 'Save current message as a draft',
24+
'key_category': 'general',
25+
}),
26+
('OPEN_DRAFT', {
27+
'keys': {'d'},
28+
'help_text': 'Open draft message saved in this session',
29+
'key_category': 'general',
30+
}),
2131
('ABOUT', {
2232
'keys': {'meta ?'},
2333
'help_text': 'Show/hide about menu',

zulipterminal/core.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ def search_messages(self, text: str) -> None:
174174
if 0 <= focus_position < len(w_list):
175175
self.view.message_view.set_focus(focus_position)
176176

177+
def save_draft_confirmation_popup(self, message: Message) -> None:
178+
question = urwid.Text('Save this message as a draft?'
179+
' (This will overwrite the existing draft.)')
180+
save_draft = partial(self.model.save_draft, message)
181+
self.loop.widget = PopUpConfirmationView(self, question, save_draft)
182+
177183
def stream_muting_confirmation_popup(self, button: Any) -> None:
178184
currently_muted = self.model.is_muted_stream(button.stream_id)
179185
type_of_action = "unmuting" if currently_muted else "muting"

zulipterminal/model.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def __init__(self, controller: Any) -> None:
135135

136136
self.unread_counts = classify_unread_counts(self)
137137

138+
self.draft = None # type: Optional[Message]
138139
self.new_user_input = True
139140
self._start_presence_updates()
140141

@@ -285,6 +286,13 @@ def react_to_message(self,
285286
response = self.client.add_reaction(reaction_to_toggle_spec)
286287
display_error_if_present(response, self.controller)
287288

289+
def session_draft_message(self) -> Optional[Message]:
290+
return self.draft
291+
292+
def save_draft(self, message: Message) -> None:
293+
self.draft = message
294+
self.controller.view.set_footer_text("Saved message as draft", 3)
295+
288296
@asynch
289297
def toggle_message_star_status(self, message: Message) -> None:
290298
base_request = dict(flag='starred', messages=[message['id']])

zulipterminal/ui.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,27 @@ def keypress(self, size: Tuple[int, int], key: str) -> Optional[str]:
217217
search_box.set_edit_text("")
218218
self.controller.enter_editor_mode_with(search_box)
219219
return key
220+
elif is_command_key('OPEN_DRAFT', key):
221+
draft = self.model.session_draft_message()
222+
if draft:
223+
if draft['type'] == 'stream':
224+
self.write_box.stream_box_view(
225+
caption=draft['display_recipient'],
226+
title=draft['subject'],
227+
stream_id=draft['stream_id'],
228+
)
229+
elif draft['type'] == 'private':
230+
self.write_box.private_box_view(
231+
email=draft['display_recipient'],
232+
)
233+
content = draft['content']
234+
self.write_box.msg_write_box.edit_text = content
235+
self.write_box.msg_write_box.edit_pos = len(content)
236+
self.middle_column.set_focus('footer')
237+
else:
238+
self.set_footer_text('No draft message was saved in'
239+
' this session.', 3)
240+
return key
220241
elif is_command_key('ABOUT', key):
221242
self.controller.show_about()
222243
return key

zulipterminal/ui_tools/boxes.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,26 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
307307
self.view.controller.exit_editor_mode()
308308
self.main_view(False)
309309
self.view.middle_column.set_focus('body')
310+
elif is_command_key('SAVE_AS_DRAFT', key):
311+
if not self.msg_edit_id:
312+
if self.to_write_box:
313+
message = Message(
314+
display_recipient=self.to_write_box.edit_text,
315+
content=self.msg_write_box.edit_text,
316+
type='private',
317+
)
318+
elif self.stream_id:
319+
message = Message(
320+
display_recipient=self.stream_write_box.edit_text,
321+
content=self.msg_write_box.edit_text,
322+
subject=self.title_write_box.edit_text,
323+
stream_id=self.stream_id,
324+
type='stream',
325+
)
326+
if not self.model.draft:
327+
self.model.save_draft(message)
328+
if message != self.model.draft:
329+
self.view.controller.save_draft_confirmation_popup(message)
310330
elif is_command_key('CYCLE_COMPOSE_FOCUS', key):
311331
if len(self.contents) == 0:
312332
return key

0 commit comments

Comments
 (0)