mirror of
https://github.com/paul-nameless/tg
synced 2024-11-22 03:43:19 +00:00
Do curses draw in one thread
This commit is contained in:
parent
e41ab35a9e
commit
ca81118f48
3 changed files with 75 additions and 47 deletions
|
@ -1,6 +1,7 @@
|
|||
import curses
|
||||
import logging
|
||||
import os
|
||||
import queue
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
|
@ -45,8 +46,8 @@ class Controller:
|
|||
def __init__(self, model: Model, view: View, tg: Tdlib) -> None:
|
||||
self.model = model
|
||||
self.view = view
|
||||
self.render_lock = threading.RLock()
|
||||
self.render_status_lock = threading.RLock()
|
||||
self.queue = queue.Queue()
|
||||
self.is_running = True
|
||||
self.tg = tg
|
||||
self.chat_size = 0.5
|
||||
|
||||
|
@ -363,8 +364,10 @@ class Controller:
|
|||
return self.update_status("Info", msg)
|
||||
|
||||
def update_status(self, level: str, msg: str):
|
||||
with self.render_status_lock:
|
||||
self.view.status.draw(f"{level}: {msg}")
|
||||
self.queue.put(partial(self._update_status, level, msg))
|
||||
|
||||
def _update_status(self, level: str, msg: str):
|
||||
self.view.status.draw(f"{level}: {msg}")
|
||||
|
||||
def edit_msg(self):
|
||||
msg = MsgProxy(self.model.current_msg)
|
||||
|
@ -400,9 +403,13 @@ class Controller:
|
|||
def run(self) -> None:
|
||||
try:
|
||||
self.handle(self.chat_bindings, 0.5)
|
||||
self.queue.put(self.close)
|
||||
except Exception:
|
||||
log.exception("Error happened in main loop")
|
||||
|
||||
def close(self):
|
||||
self.is_running = False
|
||||
|
||||
def handle_msgs(self, _: int):
|
||||
rc = self.handle(self.msg_bindings, 0.2)
|
||||
if rc == "QUIT":
|
||||
|
@ -431,6 +438,9 @@ class Controller:
|
|||
self.resize()
|
||||
|
||||
def resize(self):
|
||||
self.queue.put(self._resize)
|
||||
|
||||
def _resize(self):
|
||||
rows, cols = self.view.stdscr.getmaxyx()
|
||||
# If we didn't clear the screen before doing this,
|
||||
# the original window contents would remain on the screen
|
||||
|
@ -443,24 +453,35 @@ class Controller:
|
|||
self.view.status.resize(rows, cols)
|
||||
self.render()
|
||||
|
||||
def render(self) -> None:
|
||||
with self.render_lock:
|
||||
# using lock here, because render is used from another
|
||||
# thread by tdlib python wrapper
|
||||
page_size = self.view.chats.h
|
||||
chats = self.model.get_chats(
|
||||
self.model.current_chat, page_size, MSGS_LEFT_SCROLL_THRESHOLD
|
||||
)
|
||||
selected_chat = min(
|
||||
self.model.current_chat, page_size - MSGS_LEFT_SCROLL_THRESHOLD
|
||||
)
|
||||
def draw(self):
|
||||
while self.is_running:
|
||||
try:
|
||||
log.info("Queue size: %d", self.queue.qsize())
|
||||
fun = self.queue.get()
|
||||
fun()
|
||||
except Exception:
|
||||
log.exception("Error happened in draw loop")
|
||||
|
||||
self.view.chats.draw(selected_chat, chats)
|
||||
self.render_msgs()
|
||||
with self.render_status_lock:
|
||||
self.view.status.draw()
|
||||
def render(self) -> None:
|
||||
self.queue.put(self._render)
|
||||
|
||||
def _render(self) -> None:
|
||||
page_size = self.view.chats.h
|
||||
chats = self.model.get_chats(
|
||||
self.model.current_chat, page_size, MSGS_LEFT_SCROLL_THRESHOLD
|
||||
)
|
||||
selected_chat = min(
|
||||
self.model.current_chat, page_size - MSGS_LEFT_SCROLL_THRESHOLD
|
||||
)
|
||||
|
||||
self.view.chats.draw(selected_chat, chats)
|
||||
self.render_msgs()
|
||||
self.view.status.draw()
|
||||
|
||||
def render_msgs(self) -> None:
|
||||
self.queue.put(self._render_msgs)
|
||||
|
||||
def _render_msgs(self) -> None:
|
||||
current_msg_idx = self.model.get_current_chat_msg_idx()
|
||||
if current_msg_idx is None:
|
||||
return
|
||||
|
|
|
@ -36,9 +36,11 @@ def run(tg: Tdlib, stdscr: window) -> None:
|
|||
for msg_type, handler in update_handlers.handlers.items():
|
||||
tg.add_update_handler(msg_type, partial(handler, controller))
|
||||
|
||||
t = threading.Thread(target=controller.run,)
|
||||
t.start()
|
||||
t.join()
|
||||
thread = threading.Thread(target=controller.run,)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
controller.draw()
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
from typing import Any, Callable, Dict
|
||||
|
||||
|
@ -69,8 +70,8 @@ def update_chat_order(controller: Controller, update: Dict[str, Any]):
|
|||
chat_id = update["chat_id"]
|
||||
order = update["order"]
|
||||
|
||||
controller.model.chats.update_chat(chat_id, order=order)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
if controller.model.chats.update_chat(chat_id, order=order):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatTitle")
|
||||
|
@ -80,8 +81,8 @@ def update_chat_title(controller: Controller, update: Dict[str, Any]):
|
|||
title = update["title"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(chat_id, title=title)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
if controller.model.chats.update_chat(chat_id, title=title):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatIsMarkedAsUnread")
|
||||
|
@ -93,10 +94,10 @@ def update_chat_marked_as_unread(
|
|||
is_marked_as_unread = update["is_marked_as_unread"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(
|
||||
if controller.model.chats.update_chat(
|
||||
chat_id, is_marked_as_unread=is_marked_as_unread
|
||||
)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatIsPinned")
|
||||
|
@ -107,10 +108,10 @@ def update_chat_is_pinned(controller: Controller, update: Dict[str, Any]):
|
|||
order = update["order"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(
|
||||
if controller.model.chats.update_chat(
|
||||
chat_id, is_pinned=is_pinned, order=order
|
||||
)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatReadOutbox")
|
||||
|
@ -120,10 +121,10 @@ def update_chat_read_outbox(controller: Controller, update: Dict[str, Any]):
|
|||
last_read_outbox_message_id = update["last_read_outbox_message_id"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(
|
||||
if controller.model.chats.update_chat(
|
||||
chat_id, last_read_outbox_message_id=last_read_outbox_message_id,
|
||||
)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatReadInbox")
|
||||
|
@ -134,12 +135,12 @@ def update_chat_read_inbox(controller: Controller, update: Dict[str, Any]):
|
|||
unread_count = update["unread_count"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(
|
||||
if controller.model.chats.update_chat(
|
||||
chat_id,
|
||||
last_read_inbox_message_id=last_read_inbox_message_id,
|
||||
unread_count=unread_count,
|
||||
)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatDraftMessage")
|
||||
|
@ -151,22 +152,26 @@ def update_chat_draft_msg(controller: Controller, update: Dict[str, Any]):
|
|||
order = update["order"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(chat_id, order=order)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
if controller.model.chats.update_chat(chat_id, order=order):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatLastMessage")
|
||||
def update_chat_last_msg(controller: Controller, update: Dict[str, Any]):
|
||||
log.info("Proccessing updateChatLastMessage")
|
||||
chat_id = update["chat_id"]
|
||||
message = update["last_message"]
|
||||
last_message = update.get("last_message")
|
||||
if not last_message:
|
||||
# according to documentation it can be null
|
||||
log.warning("last_message is null: %s", update)
|
||||
return
|
||||
order = update["order"]
|
||||
|
||||
current_chat_id = controller.model.current_chat_id
|
||||
controller.model.chats.update_chat(
|
||||
if controller.model.chats.update_chat(
|
||||
chat_id, last_message=message, order=order
|
||||
)
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
):
|
||||
controller._refresh_current_chat(current_chat_id)
|
||||
|
||||
|
||||
@update_handler("updateChatNotificationSettings")
|
||||
|
@ -174,10 +179,10 @@ def update_chat_notification_settings(controller: Controller, update):
|
|||
log.info("Proccessing update_chat_notification_settings")
|
||||
chat_id = update["chat_id"]
|
||||
notification_settings = update["notification_settings"]
|
||||
controller.model.chats.update_chat(
|
||||
if controller.model.chats.update_chat(
|
||||
chat_id, notification_settings=notification_settings
|
||||
)
|
||||
controller.render()
|
||||
):
|
||||
controller.render()
|
||||
|
||||
|
||||
@update_handler("updateMessageSendSucceeded")
|
||||
|
|
Loading…
Reference in a new issue