Skip to content

Commit b79782b

Browse files
Merge pull request #88 from duynguyenhoang/feature/fix_list_starred_with_unread_count
Fix unread message for starred items
2 parents c2777ec + cae6b6c commit b79782b

File tree

4 files changed

+158
-29
lines changed

4 files changed

+158
-29
lines changed

app.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from sclack.themes import themes
2424

2525
from sclack.widgets.set_snooze import SetSnoozeWidget
26+
from sclack.utils.channel import is_dm, is_group, is_channel
2627

2728
loop = asyncio.get_event_loop()
2829

@@ -157,26 +158,27 @@ def mount_sidebar(self, executor):
157158

158159
# Prepare list of Star users and channels
159160
for dm in self.store.state.stars:
160-
# Group chat is not supported, prefer to https://github.com/haskellcamargo/sclack/issues/67
161-
if self.store.is_dm(dm['channel']):
161+
if is_dm(dm['channel']):
162162
detail = self.store.get_channel_info(dm['channel'])
163163
user = self.store.find_user_by_id(detail['user'])
164+
164165
if user:
165166
stars_user_id.append(user['id'])
166167
star_user_tmp.append(Dm(
167168
dm['channel'],
168169
name=self.store.get_user_display_name(user),
169-
user=dm['channel'],
170+
user=user['id'],
170171
you=False
171172
))
172-
elif self.store.is_channel(dm['channel']):
173+
elif is_channel(dm['channel']) or is_group(dm['channel']):
173174
channel = self.store.get_channel_info(dm['channel'])
174-
if channel:
175+
# Group chat (is_mpim) is not supported, prefer to https://github.com/haskellcamargo/sclack/issues/67
176+
if channel and not channel.get('is_archived', False) and not channel.get('is_mpim', False):
175177
stars_channel_id.append(channel['id'])
176178
stars.append(Channel(
177179
id=channel['id'],
178180
name=channel['name'],
179-
is_private=channel['is_private']
181+
is_private=channel.get('is_private', True)
180182
))
181183
stars.extend(star_user_tmp)
182184

@@ -206,9 +208,9 @@ def mount_sidebar(self, executor):
206208

207209
self.sidebar = SideBar(profile, channels, dms, stars=stars, title=self.store.state.auth['team'])
208210
urwid.connect_signal(self.sidebar, 'go_to_channel', self.go_to_channel)
209-
loop.create_task(self.get_channels_info(executor, channels))
210-
loop.create_task(self.get_presences(executor, dms))
211-
loop.create_task(self.get_dms_unread(executor, dms))
211+
loop.create_task(self.get_channels_info(executor, self.sidebar.get_all_channels()))
212+
loop.create_task(self.get_presences(executor, self.sidebar.get_all_dms()))
213+
loop.create_task(self.get_dms_unread(executor, self.sidebar.get_all_dms()))
212214

213215
@asyncio.coroutine
214216
def get_presences(self, executor, dm_widgets):
@@ -693,16 +695,27 @@ def stop_typing(*args):
693695
self.chatbox.message_box.typing = None
694696

695697
alarm = None
698+
696699
while self.store.slack.server.connected is True:
697700
events = self.store.slack.rtm_read()
701+
698702
for event in events:
699703
if event.get('type') == 'hello':
700704
pass
701-
elif event.get('type') in ('channel_marked', 'group_marked'):
705+
elif event.get('type') in ('channel_marked', 'group_marked', 'im_marked'):
702706
unread = event.get('unread_count_display', 0)
703-
for channel in self.sidebar.channels:
704-
if channel.id == event['channel']:
705-
channel.set_unread(unread)
707+
708+
if event.get('type') == 'channel_marked':
709+
targets = self.sidebar.get_all_channels()
710+
elif event.get('type') == 'group_marked':
711+
targets = self.sidebar.get_all_groups()
712+
else:
713+
targets = self.sidebar.get_all_dms()
714+
715+
for target in targets:
716+
if target.id == event['channel']:
717+
target.set_unread(unread)
718+
706719
elif event['type'] == 'message':
707720
loop.create_task(
708721
self.update_chat(event)

sclack/components.py

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .emoji import emoji_codemap
1111
from .markdown import MarkdownText
1212
from .store import Store
13+
from sclack.utils.channel import is_group, is_channel, is_dm
1314

1415

1516
MARK_READ_ALARM_PERIOD = 3
@@ -370,16 +371,21 @@ def handle_floating_date(self, size):
370371

371372

372373
class Dm(urwid.AttrMap):
373-
def __init__(self, id, name, user, you=False, unread=0):
374+
def __init__(self, id, name, user, you=False, unread=0, is_selected=False):
374375
self.id = id
375376
self.user = user
376377
self.name = name
377378
self.you = you
378379
self.presence = 'away'
379380
self.unread = unread
380381
self.body = urwid.SelectableIcon(self.get_markup())
381-
self.is_selected = False
382-
super(Dm, self).__init__(self.body, 'inactive', 'active_channel')
382+
self.is_selected = is_selected
383+
384+
attr_map = 'inactive'
385+
if is_selected:
386+
attr_map = 'selected_channel'
387+
388+
super(Dm, self).__init__(self.body, attr_map, 'active_channel')
383389

384390
def get_markup(self, presence='away'):
385391
if self.user == 'USLACKBOT':
@@ -417,11 +423,11 @@ def get_markup(self, presence='away'):
417423

418424
def set_unread(self, count):
419425
self.unread = count
420-
421-
if count > 0:
422-
self.attr_map = {None: 'unread_channel'}
423-
else:
424-
self.attr_map = {None: 'inactive'}
426+
if not self.is_selected:
427+
if count > 0:
428+
self.attr_map = {None: 'unread_channel'}
429+
else:
430+
self.attr_map = {None: 'inactive'}
425431

426432
self.body.set_text(self.get_markup(self.presence))
427433

@@ -440,12 +446,15 @@ def select(self):
440446
'presence_away': 'selected_channel'
441447
}
442448
self.set_presence(self.presence)
449+
self.attr_map = {None: 'selected_channel'}
450+
self.focus_map = {None: 'selected_channel'}
443451

444452
def deselect(self):
445453
self.is_selected = False
446454
self.attr_map = {None: None}
447455
self.set_presence(self.presence)
448456

457+
449458
class Fields(urwid.Pile):
450459
def chunks(self, list, size):
451460
for i in range(0, len(list), size):
@@ -650,6 +659,7 @@ def text(self, text):
650659
self.prompt_widget.set_edit_text(text)
651660
self.prompt_widget.set_edit_pos(len(text))
652661

662+
653663
class MessagePrompt(urwid_readline.ReadlineEdit):
654664
__metaclass__ = urwid.MetaSignals
655665
signals = ['submit_message', 'go_to_last_message']
@@ -748,6 +758,7 @@ def __init__(self, profile, channels=(), dms=(), stars=(), title=''):
748758
self.channels = channels
749759
self.stars = stars
750760
self.dms = dms
761+
self.groups = ()
751762

752763
# Subscribe to receive message from channels to select them
753764
for channel in self.channels:
@@ -768,13 +779,72 @@ def __init__(self, profile, channels=(), dms=(), stars=(), title=''):
768779
self.listbox = urwid.ListBox(self.walker)
769780
super(SideBar, self).__init__(self.listbox, header=header, footer=footer)
770781

782+
def get_all_channels(self):
783+
"""
784+
List Channels including Starred items
785+
:return:
786+
"""
787+
channels_starred = list(filter(
788+
lambda starred: is_channel(starred.id),
789+
self.stars
790+
))
791+
channels_starred.extend(self.channels)
792+
793+
return channels_starred
794+
795+
def get_all_dms(self):
796+
"""
797+
List DM including Starred items
798+
:return:
799+
"""
800+
dms = list(filter(
801+
lambda starred: is_dm(starred.id),
802+
self.stars
803+
))
804+
dms.extend(self.dms)
805+
806+
return dms
807+
808+
def get_all_groups(self):
809+
"""
810+
List Groups including Starred items
811+
:return:
812+
"""
813+
groups = list(filter(
814+
lambda starred: is_group(starred.id),
815+
self.stars
816+
))
817+
groups.extend(self.groups)
818+
819+
return groups
820+
821+
def get_targets_by_id(self, channel_id):
822+
"""
823+
For different channel_id we get different data from: Groups, DMs, Channels
824+
:param channel_id:
825+
:return:
826+
"""
827+
targets = None
828+
if is_channel(channel_id):
829+
targets = self.get_all_channels()
830+
elif is_dm(channel_id):
831+
targets = self.get_all_dms()
832+
elif is_group(channel_id):
833+
targets = self.get_all_groups()
834+
return targets
835+
771836
def select_channel(self, channel_id):
772-
for channel in self.channels:
837+
"""
838+
:param channel_id:
839+
:return:
840+
"""
841+
for channel in self.get_all_channels():
773842
if channel.id == channel_id:
774843
channel.select()
775844
else:
776845
channel.deselect()
777-
for dm in self.dms:
846+
847+
for dm in self.get_all_dms():
778848
if dm.id == channel_id:
779849
dm.select()
780850
else:
@@ -787,11 +857,7 @@ def update_items(self, event):
787857
:return:
788858
"""
789859
channel_id = event.get('channel')
790-
791-
if channel_id[0] == 'D':
792-
target = self.dms
793-
else:
794-
target = self.channels
860+
target = self.get_targets_by_id(channel_id)
795861

796862
chat_detail = Store.instance.get_channel_info(event.get('channel'))
797863
new_count = chat_detail.get('unread_count_display', 0)

sclack/store.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ def __init__(self):
2020
self.online_users = set()
2121
self.is_snoozed = False
2222

23+
2324
class Cache:
2425
def __init__(self):
2526
self.avatar = {}
2627
self.picture = {}
2728

29+
2830
class Store:
2931
def __init__(self, workspaces, config):
3032
self.workspaces = workspaces
@@ -165,7 +167,7 @@ def load_stars(self):
165167
:return:
166168
"""
167169
self.state.stars = list(filter(
168-
lambda star: star.get('type', '') in ('channel', 'im', 'group', ),
170+
lambda star: star.get('type', '') in ('channel', 'im', 'group',),
169171
self.slack.api_call('stars.list')['items']
170172
))
171173

sclack/utils/channel.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
def get_group_name(group_raw_name):
2+
"""
3+
TODO Remove last number
4+
:param group_raw_name:
5+
:return:
6+
"""
7+
if group_raw_name[:5] == 'mpdm-':
8+
group_parts = group_raw_name[5:].split('--')
9+
group_parts = ['@{}'.format(item) for item in group_parts]
10+
return ', '.join(group_parts)
11+
12+
return group_raw_name
13+
14+
15+
def is_valid_channel_id(channel_id):
16+
"""
17+
Check whether channel_id is valid
18+
:param channel_id:
19+
:return:
20+
"""
21+
return channel_id[0] in ('C', 'G', 'D')
22+
23+
24+
def is_channel(channel_id):
25+
"""
26+
Is a channel
27+
:param channel_id:
28+
:return:
29+
"""
30+
return channel_id[0] == 'C'
31+
32+
33+
def is_dm(channel_id):
34+
"""
35+
Is direct message
36+
:param channel_id:
37+
:return:
38+
"""
39+
return channel_id[0] == 'D'
40+
41+
42+
def is_group(channel_id):
43+
"""
44+
Is a group
45+
:param channel_id:
46+
:return:
47+
"""
48+
return channel_id[0] == 'G'

0 commit comments

Comments
 (0)