mirror of
https://github.com/paul-nameless/tg
synced 2025-02-17 02:58:24 +00:00
Merge pull request #35 from paul-nameless/chats-scrolling
Chats scrolling
This commit is contained in:
commit
35ee2b58f5
3 changed files with 127 additions and 15 deletions
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Dict, Any, Optional
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -47,7 +48,14 @@ class Controller:
|
||||||
self.tg = tg
|
self.tg = tg
|
||||||
self.handlers = {
|
self.handlers = {
|
||||||
"updateNewMessage": self.update_new_msg,
|
"updateNewMessage": self.update_new_msg,
|
||||||
|
"updateMessageContent": self.update_msg_content,
|
||||||
|
"updateChatIsPinned": self.update_chat_is_pinned,
|
||||||
|
"updateChatIsMarkedAsUnread": self.update_chat_marked_as_unread,
|
||||||
|
"updateChatReadInbox": self.update_chat_read_inbox,
|
||||||
|
"updateChatTitle": self.update_chat_title,
|
||||||
"updateChatLastMessage": self.update_chat_last_msg,
|
"updateChatLastMessage": self.update_chat_last_msg,
|
||||||
|
"updateChatDraftMessage": self.update_chat_draft_msg,
|
||||||
|
"updateChatOrder": self.update_chat_order,
|
||||||
"updateMessageSendSucceeded": self.update_msg_send_succeeded,
|
"updateMessageSendSucceeded": self.update_msg_send_succeeded,
|
||||||
"updateFile": self.update_file,
|
"updateFile": self.update_file,
|
||||||
}
|
}
|
||||||
|
@ -278,6 +286,16 @@ class Controller:
|
||||||
)
|
)
|
||||||
self.view.msgs.draw(current_msg_idx, msgs, MSGS_LEFT_SCROLL_THRESHOLD)
|
self.view.msgs.draw(current_msg_idx, msgs, MSGS_LEFT_SCROLL_THRESHOLD)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_msg_content(self, update):
|
||||||
|
content = MsgProxy(update["new_content"])
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
message_id = update["message_id"]
|
||||||
|
self.model.msgs.update_msg_content(chat_id, message_id, content)
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
if current_chat_id == chat_id:
|
||||||
|
self.refresh_msgs()
|
||||||
|
|
||||||
@handle_exception
|
@handle_exception
|
||||||
def update_new_msg(self, update):
|
def update_new_msg(self, update):
|
||||||
msg = MsgProxy(update["message"])
|
msg = MsgProxy(update["message"])
|
||||||
|
@ -289,6 +307,9 @@ class Controller:
|
||||||
if msg.file_id and msg.size <= config.max_download_size:
|
if msg.file_id and msg.size <= config.max_download_size:
|
||||||
self.download(msg.file_id, chat_id, msg["id"])
|
self.download(msg.file_id, chat_id, msg["id"])
|
||||||
|
|
||||||
|
self._notify_for_message(chat_id, msg)
|
||||||
|
|
||||||
|
def _notify_for_message(self, chat_id: int, msg: Dict[str, Any]):
|
||||||
# do not notify, if muted
|
# do not notify, if muted
|
||||||
# TODO: optimize
|
# TODO: optimize
|
||||||
chat = None
|
chat = None
|
||||||
|
@ -318,12 +339,85 @@ class Controller:
|
||||||
notify(text, title=name)
|
notify(text, title=name)
|
||||||
|
|
||||||
@handle_exception
|
@handle_exception
|
||||||
def update_chat_last_msg(self, update):
|
def update_chat_order(self, update: Dict[str, Any]):
|
||||||
|
log.info("Proccessing updateChatOrder")
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
order = update["order"]
|
||||||
|
|
||||||
|
self.model.chats.update_chat(chat_id, order=order)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_chat_title(self, update: Dict[str, Any]):
|
||||||
|
log.info("Proccessing updateChatTitle")
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
title = update["title"]
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
self.model.chats.update_chat(chat_id, title=title)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_chat_marked_as_unread(self, update: Dict[str, Any]):
|
||||||
|
log.info("Proccessing updateChatIsMarkedAsUnread")
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
is_marked_as_unread = update["is_marked_as_unread"]
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
self.model.chats.update_chat(
|
||||||
|
chat_id, is_marked_as_unread=is_marked_as_unread
|
||||||
|
)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_chat_is_pinned(self, update: Dict[str, Any]):
|
||||||
|
log.info("Proccessing updateChatIsPinned")
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
is_pinned = update["is_pinned"]
|
||||||
|
order = update["order"]
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
self.model.chats.update_chat(chat_id, is_pinned=is_pinned, order=order)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_chat_read_inbox(self, update: Dict[str, Any]):
|
||||||
|
log.info("Proccessing updateChatReadInbox")
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
last_read_inbox_message_id = update["last_read_inbox_message_id"]
|
||||||
|
unread_count = update["unread_count"]
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
self.model.chats.update_chat(
|
||||||
|
chat_id,
|
||||||
|
last_read_inbox_message_id=last_read_inbox_message_id,
|
||||||
|
unread_count=unread_count,
|
||||||
|
)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_chat_draft_msg(self, update: Dict[str, Any]):
|
||||||
|
log.info("Proccessing updateChatDraftMessage")
|
||||||
|
chat_id = update["chat_id"]
|
||||||
|
# FIXME: ignoring draft message itself for now because UI can't show it
|
||||||
|
# draft_message = update["draft_message"]
|
||||||
|
order = update["order"]
|
||||||
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
|
self.model.chats.update_chat(chat_id, order=order)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def update_chat_last_msg(self, update: Dict[str, Any]):
|
||||||
log.info("Proccessing updateChatLastMessage")
|
log.info("Proccessing updateChatLastMessage")
|
||||||
chat_id = update["chat_id"]
|
chat_id = update["chat_id"]
|
||||||
message = update["last_message"]
|
message = update["last_message"]
|
||||||
|
order = update["order"]
|
||||||
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
current_chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||||
self.model.chats.update_last_message(chat_id, message)
|
self.model.chats.update_chat(
|
||||||
|
chat_id, last_message=message, order=order
|
||||||
|
)
|
||||||
|
self._refresh_current_chat(current_chat_id)
|
||||||
|
|
||||||
|
def _refresh_current_chat(self, current_chat_id: Optional[int]):
|
||||||
|
if current_chat_id is None:
|
||||||
|
return
|
||||||
# TODO: we can create <index> for chats, it's faster than sqlite anyway
|
# TODO: we can create <index> for chats, it's faster than sqlite anyway
|
||||||
# though need to make sure that creatinng index is atomic operation
|
# though need to make sure that creatinng index is atomic operation
|
||||||
# requires locks for read, until index and chats will be the same
|
# requires locks for read, until index and chats will be the same
|
||||||
|
|
|
@ -174,18 +174,19 @@ class ChatModel:
|
||||||
return {}
|
return {}
|
||||||
return result.update
|
return result.update
|
||||||
|
|
||||||
def update_last_message(self, chat_id, message):
|
def update_chat(self, chat_id: int, **updates: Dict[str, Any]) -> bool:
|
||||||
for i, c in enumerate(self.chats):
|
for i, c in enumerate(self.chats):
|
||||||
if c["id"] != chat_id:
|
if c["id"] != chat_id:
|
||||||
continue
|
continue
|
||||||
self.chats[i]["last_message"] = message
|
self.chats[i].update(updates)
|
||||||
self.chats = sorted(
|
self.chats = sorted(
|
||||||
self.chats,
|
self.chats,
|
||||||
key=lambda it: it["last_message"]["date"],
|
# recommended chat order, for more info see
|
||||||
|
# https://core.telegram.org/tdlib/getting-started#getting-the-lists-of-chats
|
||||||
|
key=lambda it: (it["order"], it["id"]),
|
||||||
reverse=True,
|
reverse=True,
|
||||||
)
|
)
|
||||||
|
log.info(f"Updated chat with keys {list(updates)}")
|
||||||
log.info("Updated last message")
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
log.error(f"Can't find chat {chat_id} in existing chats")
|
log.error(f"Can't find chat {chat_id} in existing chats")
|
||||||
|
@ -232,6 +233,16 @@ class MsgModel:
|
||||||
msg_set.remove(msg_id)
|
msg_set.remove(msg_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def update_msg_content(
|
||||||
|
self, chat_id: int, msg_id: int, message_content: Dict[str, Any]
|
||||||
|
) -> bool:
|
||||||
|
log.info(f"updating {msg_id=} {message_content=}")
|
||||||
|
for msg in self.msgs[chat_id]:
|
||||||
|
if msg["id"] != msg_id:
|
||||||
|
continue
|
||||||
|
msg["content"] = message_content
|
||||||
|
return True
|
||||||
|
|
||||||
def add_message(self, chat_id: int, message: Dict[str, Any]) -> bool:
|
def add_message(self, chat_id: int, message: Dict[str, Any]) -> bool:
|
||||||
msg_id = message["id"]
|
msg_id = message["id"]
|
||||||
msg_set = self.msg_ids[chat_id]
|
msg_set = self.msg_ids[chat_id]
|
||||||
|
|
|
@ -145,12 +145,13 @@ class ChatView:
|
||||||
self.win.vline(0, self.w - 1, curses.ACS_VLINE, self.h)
|
self.win.vline(0, self.w - 1, curses.ACS_VLINE, self.h)
|
||||||
for i, chat in enumerate(chats):
|
for i, chat in enumerate(chats):
|
||||||
is_selected = i == current
|
is_selected = i == current
|
||||||
date, title, unread_count, last_msg = (
|
unread_count = (
|
||||||
get_date(chat),
|
chat["unread_count"] or 1 if chat["is_marked_as_unread"] else 0
|
||||||
chat["title"],
|
|
||||||
chat["unread_count"],
|
|
||||||
get_last_msg(chat),
|
|
||||||
)
|
)
|
||||||
|
date = get_date(chat)
|
||||||
|
title = chat["title"]
|
||||||
|
is_pinned = chat["is_pinned"]
|
||||||
|
last_msg = get_last_msg(chat)
|
||||||
offset = 0
|
offset = 0
|
||||||
for attr, elem in zip(
|
for attr, elem in zip(
|
||||||
self._msg_attribures(is_selected), [f"{date} ", title]
|
self._msg_attribures(is_selected), [f"{date} ", title]
|
||||||
|
@ -173,7 +174,9 @@ class ChatView:
|
||||||
|
|
||||||
self.win.addstr(i, offset, last_msg, self._msg_color(is_selected))
|
self.win.addstr(i, offset, last_msg, self._msg_color(is_selected))
|
||||||
|
|
||||||
if left_label := self._get_chat_label(unread_count, chat):
|
if left_label := self._get_chat_label(
|
||||||
|
unread_count, is_pinned, chat
|
||||||
|
):
|
||||||
self.win.addstr(
|
self.win.addstr(
|
||||||
i,
|
i,
|
||||||
self.w - len(left_label) - 1,
|
self.w - len(left_label) - 1,
|
||||||
|
@ -184,10 +187,14 @@ class ChatView:
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_chat_label(unread_count: int, chat: Dict[str, Any]) -> str:
|
def _get_chat_label(
|
||||||
|
unread_count: int, is_pinned: bool, chat: Dict[str, Any]
|
||||||
|
) -> str:
|
||||||
label = ""
|
label = ""
|
||||||
|
if is_pinned:
|
||||||
|
label += "pinned "
|
||||||
if unread_count:
|
if unread_count:
|
||||||
label = f"{unread_count} "
|
label += f"{unread_count} "
|
||||||
|
|
||||||
if chat["notification_settings"]["mute_for"]:
|
if chat["notification_settings"]["mute_for"]:
|
||||||
label = f"muted {label}"
|
label = f"muted {label}"
|
||||||
|
|
Loading…
Add table
Reference in a new issue