Introduced more (configurable) colours in chat messages to better distinguish different message types

This commit is contained in:
Maarten van Gompel 2022-12-13 13:54:15 +01:00
parent 2b0c0cf199
commit d76891a578
2 changed files with 64 additions and 28 deletions

View file

@ -5,6 +5,7 @@ overwritten by external config file
import os import os
import platform import platform
import runpy import runpy
import tg.colors
from typing import Dict, Optional from typing import Dict, Optional
_os_name = platform.system() _os_name = platform.system()
@ -74,6 +75,20 @@ URL_VIEW = "urlview"
USERS_COLORS = tuple(range(2, 16)) USERS_COLORS = tuple(range(2, 16))
COLOR_TITLE = tg.colors.cyan
COLOR_TIME = tg.colors.cyan
COLOR_FLAGS = tg.colors.yellow
COLOR_UNREAD_COUNT = tg.colors.yellow
COLOR_MSG_MINE = -1 #unset
BGCOLOR_MSG_MINE = tg.colors.black
COLOR_MSG_MEDIA = tg.colors.magenta
COLOR_MSG_URL = tg.colors.blue
COLOR_MSG_REPLY = tg.colors.cyan
COLOR_MSG_NORMAL = tg.colors.white
#preview of last message in chat window
COLOR_MSG_LAST = tg.colors.white
KEEP_MEDIA = 7 KEEP_MEDIA = 7
FILE_PICKER_CMD = "ranger --choosefile={file_path}" FILE_PICKER_CMD = "ranger --choosefile={file_path}"

View file

@ -6,7 +6,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union, cast
from _curses import window # type: ignore from _curses import window # type: ignore
from tg import config from tg import config
from tg.colors import bold, cyan, get_color, magenta, reverse, white, yellow from tg.colors import bold, get_color, reverse, white
from tg.models import Model, UserModel from tg.models import Model, UserModel
from tg.msg import MsgProxy from tg.msg import MsgProxy
from tg.tdlib import ChatType, get_chat_type, is_group from tg.tdlib import ChatType, get_chat_type, is_group
@ -171,13 +171,13 @@ class ChatView:
self.win.resize(self.h, self.w) self.win.resize(self.h, self.w)
def _msg_color(self, is_selected: bool = False) -> int: def _msg_color(self, is_selected: bool = False) -> int:
color = get_color(white, -1) color = get_color(config.COLOR_MSG_LAST, -1)
if is_selected: if is_selected:
return color | reverse return color | reverse
return color return color
def _unread_color(self, is_selected: bool = False) -> int: def _unread_color(self, is_selected: bool = False) -> int:
color = get_color(magenta, -1) color = get_color(config.COLOR_UNREAD_COUNT, -1)
if is_selected: if is_selected:
return color | reverse return color | reverse
return color return color
@ -186,7 +186,7 @@ class ChatView:
self, is_selected: bool, title: str, user: Optional[str] self, is_selected: bool, title: str, user: Optional[str]
) -> Tuple[int, ...]: ) -> Tuple[int, ...]:
attrs = ( attrs = (
get_color(cyan, -1), get_color(config.COLOR_TIME, -1),
get_color(get_color_by_str(title), -1), get_color(get_color_by_str(title), -1),
get_color(get_color_by_str(user or ""), -1), get_color(get_color_by_str(user or ""), -1),
self._msg_color(is_selected), self._msg_color(is_selected),
@ -204,7 +204,7 @@ class ChatView:
self.win.vline(0, width, line, self.h) self.win.vline(0, width, line, self.h)
self.win.addstr( self.win.addstr(
0, 0, title.center(width)[:width], get_color(cyan, -1) | bold 0, 0, title.center(width)[:width], get_color(config.COLOR_TITLE, -1) | bold
) )
for i, chat in enumerate(chats, 1): for i, chat in enumerate(chats, 1):
@ -365,11 +365,12 @@ class MsgView:
def _format_reply_msg( def _format_reply_msg(
self, chat_id: int, msg: str, reply_to: int, width_limit: int self, chat_id: int, msg: str, reply_to: int, width_limit: int
) -> str: ) -> Tuple[str, bool]:
_msg = self.model.msgs.get_message(chat_id, reply_to) _msg = self.model.msgs.get_message(chat_id, reply_to)
if not _msg: if not _msg:
return msg return msg, False
reply_msg = MsgProxy(_msg) reply_msg = MsgProxy(_msg)
is_reply = False
if reply_msg_content := self._parse_msg(reply_msg): if reply_msg_content := self._parse_msg(reply_msg):
reply_sender = self.model.users.get_user_label(reply_msg.sender_id) reply_sender = self.model.users.get_user_label(reply_msg.sender_id)
sender_name = f" {reply_sender}:" if reply_sender else "" sender_name = f" {reply_sender}:" if reply_sender else ""
@ -377,37 +378,42 @@ class MsgView:
if len(reply_line) >= width_limit: if len(reply_line) >= width_limit:
reply_line = f"{reply_line[:width_limit - 4]}..." reply_line = f"{reply_line[:width_limit - 4]}..."
msg = f"{reply_line}\n{msg}" msg = f"{reply_line}\n{msg}"
return msg is_reply = True
return msg, is_reply
@staticmethod @staticmethod
def _format_url(msg_proxy: MsgProxy) -> str: def _format_url(msg_proxy: MsgProxy) -> Tuple[str, bool]:
if not msg_proxy.is_text or "web_page" not in msg_proxy.msg["content"]: if not msg_proxy.is_text or "web_page" not in msg_proxy.msg["content"]:
return "" return "", False
web = msg_proxy.msg["content"]["web_page"] web = msg_proxy.msg["content"]["web_page"]
page_type = web["type"] page_type = web["type"]
if page_type == "photo": if page_type == "photo":
return f"\n | photo: {web['url']}" return f"\n | photo: {web['url']}", True
name = web["site_name"] name = web["site_name"]
title = web["title"] title = web["title"]
description = web["description"]["text"].replace("\n", "") description = web["description"]["text"].replace("\n", "")
url = f"\n | {name}: {title}" url = f"\n | {name}: {title}"
if description: if description:
url += f"\n | {description}" url += f"\n | {description}"
return url return url, True
def _format_msg(self, msg_proxy: MsgProxy, width_limit: int) -> str: def _format_msg(self, msg_proxy: MsgProxy, width_limit: int) -> Tuple[str, bool, bool, bool, bool]:
is_reply = False
msg = self._parse_msg(msg_proxy) msg = self._parse_msg(msg_proxy)
is_media = not msg_proxy.is_text
is_me = self.model.is_me(msg_proxy["sender_id"].get("user_id"))
if caption := msg_proxy.caption: if caption := msg_proxy.caption:
msg += "\n" + caption.replace("\n", " ") msg += "\n" + caption.replace("\n", " ")
msg += self._format_url(msg_proxy) msg_fmt, is_url = self._format_url(msg_proxy)
msg += msg_fmt
if reply_to := msg_proxy.reply_msg_id: if reply_to := msg_proxy.reply_msg_id:
msg = self._format_reply_msg( msg, is_reply = self._format_reply_msg(
msg_proxy.chat_id, msg, reply_to, width_limit msg_proxy.chat_id, msg, reply_to, width_limit
) )
if reply_markup := self._format_reply_markup(msg_proxy): if reply_markup := self._format_reply_markup(msg_proxy):
msg += reply_markup msg += reply_markup
return msg return msg, is_url, is_reply, is_media, is_me
@staticmethod @staticmethod
def _format_reply_markup(msg_proxy: MsgProxy) -> str: def _format_reply_markup(msg_proxy: MsgProxy) -> str:
@ -434,7 +440,7 @@ class MsgView:
current_msg_idx: int, current_msg_idx: int,
msgs: List[Tuple[int, Dict[str, Any]]], msgs: List[Tuple[int, Dict[str, Any]]],
min_msg_padding: int, min_msg_padding: int,
) -> List[Tuple[Tuple[str, ...], bool, int]]: ) -> List[Tuple[Tuple[str, ...], bool, bool, bool, bool, bool, int]]:
""" """
Tries to collect list of messages that will satisfy `min_msg_padding` Tries to collect list of messages that will satisfy `min_msg_padding`
theshold. Long messages could prevent other messages from displaying on theshold. Long messages could prevent other messages from displaying on
@ -444,7 +450,7 @@ class MsgView:
message could be visible on the screen. message could be visible on the screen.
""" """
selected_item_idx: Optional[int] = None selected_item_idx: Optional[int] = None
collected_items: List[Tuple[Tuple[str, ...], bool, int]] = [] collected_items: List[Tuple[Tuple[str, ...], bool, bool, bool, bool, bool, int]] = []
for ignore_before in range(len(msgs)): for ignore_before in range(len(msgs)):
if selected_item_idx is not None: if selected_item_idx is not None:
break break
@ -464,7 +470,7 @@ class MsgView:
label_elements = f" {dt} ", user_id, flags label_elements = f" {dt} ", user_id, flags
label_len = sum(string_len_dwc(e) for e in label_elements) label_len = sum(string_len_dwc(e) for e in label_elements)
msg = self._format_msg( msg, is_url, is_reply, is_media, is_me = self._format_msg(
msg_proxy, width_limit=self.w - label_len - 1 msg_proxy, width_limit=self.w - label_len - 1
) )
elements = *label_elements, f" {msg}" elements = *label_elements, f" {msg}"
@ -493,9 +499,9 @@ class MsgView:
"", "",
f" ...{msg[tail_chatacters:]}", f" ...{msg[tail_chatacters:]}",
) )
collected_items.append((elements, is_selected_msg, 0)) collected_items.append((elements, is_selected_msg, is_url, is_reply, is_media, is_me, 0))
break break
collected_items.append((elements, is_selected_msg, line_num)) collected_items.append((elements, is_selected_msg, is_url, is_reply, is_media, is_me, line_num))
if is_selected_msg: if is_selected_msg:
selected_item_idx = len(collected_items) - 1 selected_item_idx = len(collected_items) - 1
if ( if (
@ -524,11 +530,11 @@ class MsgView:
if not msgs_to_draw: if not msgs_to_draw:
log.error("Can't collect message for drawing!") log.error("Can't collect message for drawing!")
for elements, selected, line_num in msgs_to_draw: for elements, selected, is_url, is_reply, is_media, is_me, line_num in msgs_to_draw:
column = 0 column = 0
user = elements[1] user = elements[1]
for attr, elem in zip( for attr, elem in zip(
self._msg_attributes(selected, user), elements self._msg_attributes(selected, is_url, is_reply, is_media, is_me, user), elements
): ):
if not elem: if not elem:
continue continue
@ -553,7 +559,7 @@ class MsgView:
column += string_len_dwc(elem) column += string_len_dwc(elem)
self.win.addstr( self.win.addstr(
0, 0, self._msg_title(chat), get_color(cyan, -1) | bold 0, 0, self._msg_title(chat), get_color(config.COLOR_TITLE, -1) | bold
) )
self._refresh() self._refresh()
@ -584,12 +590,27 @@ class MsgView:
return f"{chat['title']}: {status}".center(self.w)[: self.w] return f"{chat['title']}: {status}".center(self.w)[: self.w]
def _msg_attributes(self, is_selected: bool, user: str) -> Tuple[int, ...]: def _msg_attributes(self, is_selected: bool, is_url: bool, is_reply: bool, is_media: bool, is_me: bool, user: str) -> Tuple[int, ...]:
if is_me:
bgcolor = config.BGCOLOR_MSG_MINE
else:
bgcolor = -1
if is_me and config.COLOR_MSG_MINE != -1:
textcolor = config.COLOR_MSG_MINE
elif is_media and config.COLOR_MSG_MEDIA != -1:
textcolor = config.COLOR_MSG_MEDIA
elif is_url and config.COLOR_MSG_URL != -1:
textcolor = config.COLOR_MSG_URL
elif is_reply and config.COLOR_MSG_REPLY != -1:
textcolor = config.COLOR_MSG_REPLY
else:
textcolor = config.COLOR_MSG_NORMAL
attrs = ( attrs = (
get_color(cyan, -1), get_color(config.COLOR_TIME, -1),
get_color(get_color_by_str(user), -1), get_color(get_color_by_str(user), -1),
get_color(yellow, -1), get_color(config.COLOR_FLAGS, -1),
get_color(white, -1), get_color(textcolor, bgcolor),
) )
if is_selected: if is_selected: