Skip to content

Commit edc0342

Browse files
Merge pull request #75 from duynguyenhoang/feature/display_unread_count
Add badge to display unread count
2 parents a1a44de + ba66e6f commit edc0342

File tree

4 files changed

+157
-27
lines changed

4 files changed

+157
-27
lines changed

app.py

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
import json
66
import os
77
import requests
8-
import subprocess
98
import sys
109
import traceback
1110
import tempfile
1211
import urwid
1312
from datetime import datetime
14-
from slackclient import SlackClient
1513
from sclack.components import Attachment, Channel, ChannelHeader, ChatBox, Dm
1614
from sclack.components import Indicators, MarkdownText, Message, MessageBox
1715
from sclack.components import NewMessagesDivider, Profile, ProfileSideBar
@@ -36,6 +34,7 @@ def run(self):
3634
def set_exception_handler(self, handler):
3735
self._custom_exception_handler = handler
3836

37+
3938
class App:
4039
message_box = None
4140

@@ -165,22 +164,51 @@ def mount_sidebar(self, executor):
165164
urwid.connect_signal(self.sidebar, 'go_to_channel', self.go_to_channel)
166165
loop.create_task(self.get_channels_info(executor, channels))
167166
loop.create_task(self.get_presences(executor, dms))
167+
loop.create_task(self.get_dms_unread(executor, dms))
168168

169169
@asyncio.coroutine
170170
def get_presences(self, executor, dm_widgets):
171+
"""
172+
Compute and return presence because updating UI from another thread is unsafe
173+
:param executor:
174+
:param dm_widgets:
175+
:return:
176+
"""
171177
def get_presence(dm_widget):
172-
# Compute and return presence because updating UI from another thread is unsafe
173178
presence = self.store.get_presence(dm_widget.user)
174179
return [dm_widget, presence]
175180
presences = yield from asyncio.gather(*[
176181
loop.run_in_executor(executor, get_presence, dm_widget)
177182
for dm_widget in dm_widgets
178183
])
184+
179185
for presence in presences:
180186
[widget, response] = presence
181187
if response['ok']:
182188
widget.set_presence(response['presence'])
183189

190+
@asyncio.coroutine
191+
def get_dms_unread(self, executor, dm_widgets):
192+
"""
193+
Compute and return unread_count_display because updating UI from another thread is unsafe
194+
:param executor:
195+
:param dm_widgets:
196+
:return:
197+
"""
198+
def get_presence(dm_widget):
199+
profile_response = self.store.get_channel_info(dm_widget.id)
200+
return [dm_widget, profile_response]
201+
202+
responses = yield from asyncio.gather(*[
203+
loop.run_in_executor(executor, get_presence, dm_widget)
204+
for dm_widget in dm_widgets
205+
])
206+
207+
for profile_response in responses:
208+
[widget, response] = profile_response
209+
if response is not None:
210+
widget.set_unread(response['unread_count_display'])
211+
184212
@asyncio.coroutine
185213
def get_channels_info(self, executor, channels):
186214
def get_info(channel):
@@ -190,10 +218,20 @@ def get_info(channel):
190218
loop.run_in_executor(executor, get_info, channel)
191219
for channel in channels
192220
])
221+
193222
for channel_info in channels_info:
194223
[widget, response] = channel_info
195224
widget.set_unread(response.get('unread_count_display', 0))
196225

226+
@asyncio.coroutine
227+
def update_chat(self, event):
228+
"""
229+
Update channel/DM message count badge
230+
:param event:
231+
:return:
232+
"""
233+
self.sidebar.update_items(event)
234+
197235
@asyncio.coroutine
198236
def mount_chatbox(self, executor, channel):
199237
yield from asyncio.gather(
@@ -409,7 +447,7 @@ def lazy_load_images(self, files, widget):
409447
if not self.config['features']['pictures']:
410448
return
411449

412-
allowed_file_types = ('bmp', 'gif', 'jpeg', 'jpg', 'png')
450+
allowed_file_types = ('bmp', 'gif', 'jpeg', 'jpg', 'png')
413451

414452
for file in files:
415453
if file.get('filetype') in allowed_file_types:
@@ -420,7 +458,6 @@ def lazy_load_images(self, files, widget):
420458
not file.get('is_external', True)
421459
))
422460

423-
424461
def render_messages(self, messages):
425462
_messages = []
426463
previous_date = self.store.state.last_date
@@ -438,6 +475,7 @@ def render_messages(self, messages):
438475
date_text = 'Today'
439476
else:
440477
date_text = message_date.strftime('%A, %B %d')
478+
441479
# New messages badge
442480
if (message_datetime > last_read_datetime and not self.store.state.did_render_new_messages
443481
and (self.store.state.channel.get('unread_count_display', 0) > 0)):
@@ -530,7 +568,10 @@ def start_real_time(self):
530568
self.store.slack.rtm_connect(auto_reconnect=True)
531569

532570
def stop_typing(*args):
533-
self.chatbox.message_box.typing = None
571+
# Prevent error while switching workspace
572+
if self.chatbox is not None:
573+
self.chatbox.message_box.typing = None
574+
534575
alarm = None
535576
while self.store.slack.server.connected is True:
536577
events = self.store.slack.rtm_read()
@@ -542,9 +583,12 @@ def stop_typing(*args):
542583
for channel in self.sidebar.channels:
543584
if channel.id == event['channel']:
544585
channel.set_unread(unread)
545-
elif event.get('channel') == self.store.state.channel['id']:
546-
if event['type'] == 'message':
547-
# Delete message
586+
elif event['type'] == 'message':
587+
loop.create_task(
588+
self.update_chat(event)
589+
)
590+
591+
if event.get('channel') == self.store.state.channel['id']:
548592
if event.get('subtype') == 'message_deleted':
549593
for widget in self.chatbox.body.body:
550594
if hasattr(widget, 'ts') and getattr(widget, 'ts') == event['deleted_ts']:

0 commit comments

Comments
 (0)