diff options
-rw-r--r-- | CHANGELOG | 12 | ||||
-rw-r--r-- | data/io.poez.Poezio.appdata.xml | 51 | ||||
-rw-r--r-- | data/themes/clean.py | 193 | ||||
-rw-r--r-- | poezio/mam.py | 19 | ||||
-rw-r--r-- | poezio/tabs/muctab.py | 3 | ||||
-rw-r--r-- | poezio/ui/render.py | 7 |
6 files changed, 270 insertions, 15 deletions
@@ -11,6 +11,18 @@ https://dev.louiz.org/projects/poezio/roadmap - Contacts won’t be seen playing games or music when they actually stop doing so. - /leave now toggles off the autojoin flag instead of removing the bookmark. +- /affiliation displays things in the info win instead of directly in the room, + and additionally displays which room it refers to. +- List the correct required versions for package maintainers. +- Fix the AppStream manifest to get Flathub to accept it. +- Add a warning when the terminal doesn’t support 256color mode. +- Display our own nick properly in messages received from MAM. +- Only send an unavailable presence on closing a room if we are joined. +- Don’t display the current date for history messages received today. + +# Forgotten additions + +- Add a clean theme for light terminals, thanks Armael! * Poezio 0.13 diff --git a/data/io.poez.Poezio.appdata.xml b/data/io.poez.Poezio.appdata.xml index ce0d1a86..2ab4f79c 100644 --- a/data/io.poez.Poezio.appdata.xml +++ b/data/io.poez.Poezio.appdata.xml @@ -1,17 +1,51 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright 2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> --> +<!-- Copyright 2018-2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> --> <component type="console-application"> <id>io.poez.Poezio</id> <name>Poezio</name> <summary>Poezio is a free console XMPP client</summary> <project_license>Zlib</project_license> <metadata_license>CC0-1.0</metadata_license> + <developer_name>Poezio Team</developer_name> + <icon type="remote">https://poez.io/img/logo.svg</icon> <url type="homepage">https://poez.io</url> - <url type="bugtracker">https://dev.louiz.org/projects/poezio/issues</url> - <url type="help">https://doc.poez.io/</url> + <url type="bugtracker">https://lab.louiz.org/poezio/poezio/-/issues</url> + <url type="help">https://doc.poez.io</url> + + <description> + <p> + Poezio is a free console XMPP client (the protocol on which the Jabber IM + network is built). + </p> + <p> + Its goal is to let you connect very easily (no account creation needed) + to the network and join various chatrooms, immediately. It tries to look + like the most famous IRC clients (weechat, irssi, etc). Many commands are + identical and you won’t be lost if you already know these clients. + Configuration can be made in a configuration file or directly from the + client. + </p> + <p> + You’ll find the light, fast, geeky and anonymous spirit of IRC while + using a powerful, standard and open protocol. + </p> + + <p>Features</p> + + <ul> + <li>Encryption: TLS, OTR, always chat with encryption.</li> + <li>Chatrooms: Discuss on your favorite topics with your friends or strangers.</li> + <li>Carbon copies: Switch devices while staying in the same conversations without losing messages.</li> + <li>Plugins: Add the features you want through official or other plugins.</li> + + <li>Corrections: Fix your last sent messages.</li> + <li>Rich text: Send and receive messages with colors and formatting.</li> + <li>Chat state notifications: See the writing status of your contacts.</li> + <li>Anonymous: Use XMPP without an account.</li> + </ul> + </description> - <icon width="80" height="80">data/poezio_80.png</icon> <screenshots> <screenshot type="default"> <image>https://poez.io/img/screenshot.png</image> @@ -24,11 +58,18 @@ <category>InstantMessaging</category> <category>Network</category> </categories> + + <content_rating type="oars-1.1"> + <content_attribute id="social-chat">intense</content_attribute> + </content_rating> + <provides> <binary>poezio</binary> </provides> - <developer_name>Poezio Team</developer_name> + <releases> + <release version="0.13" date="2020-05-24"/> + <release version="0.12.1" date="2018-09-12"/> <release version="0.12" date="2018-08-13"/> <release version="0.11" date="2017-01-31"/> <release version="0.10" date="2016-10-09"/> diff --git a/data/themes/clean.py b/data/themes/clean.py new file mode 100644 index 00000000..66a18a6c --- /dev/null +++ b/data/themes/clean.py @@ -0,0 +1,193 @@ +import poezio.theming + +class CleanTheme(poezio.theming.Theme): + # Message text color + COLOR_NORMAL_TEXT = (-1, -1) + COLOR_INFORMATION_TEXT = (12, -1) # TODO + COLOR_WARNING_TEXT = (1, -1) + + # Color of the commands in the help message + COLOR_HELP_COMMANDS = (208, -1) + + # "reverse" is a special value, available only for this option. It just + # takes the nick colors and reverses it. A theme can still specify a + # fixed color if need be. + COLOR_HIGHLIGHT_NICK = "reverse" + + # Color of the participant JID in a MUC + COLOR_MUC_JID = (4, -1) + + # User list color + COLOR_USER_VISITOR = (239, -1) + COLOR_USER_PARTICIPANT = (4, -1) + COLOR_USER_NONE = (0, -1) + COLOR_USER_MODERATOR = (1, -1) + + # nickname colors + COLOR_REMOTE_USER = (13, -1) + + # The character printed in color (COLOR_STATUS_*) before the nickname + # in the user list + CHAR_STATUS = '┃' + #CHAR_STATUS = '●' + #CHAR_STATUS = '◆' + + # The characters used for the chatstates in the user list + # in a MUC + CHAR_CHATSTATE_ACTIVE = 'A' + CHAR_CHATSTATE_COMPOSING = 'X' + CHAR_CHATSTATE_PAUSED = 'p' + + # These characters are used for the affiliation in the user list + # in a MUC + CHAR_AFFILIATION_OWNER = '~' + CHAR_AFFILIATION_ADMIN = '&' + CHAR_AFFILIATION_MEMBER = '+' + CHAR_AFFILIATION_NONE = '-' + + + # XML Tab + CHAR_XML_IN = 'IN ' + CHAR_XML_OUT = 'OUT' + COLOR_XML_IN = (1, -1) + COLOR_XML_OUT = (2, -1) + + # Color for the /me message + COLOR_ME_MESSAGE = (6, -1) + + # Color for the number of revisions of a message + COLOR_REVISIONS_MESSAGE = (3, -1, 'b') + + # Color for various important text. For example the "?" before JIDs in + # the roster that require an user action. + COLOR_IMPORTANT_TEXT = (3, 5, 'b') + + # Separators + COLOR_VERTICAL_SEPARATOR = (4, -1) + COLOR_NEW_TEXT_SEPARATOR = (2, -1) + COLOR_MORE_INDICATOR = (6, 4) + + # Time + CHAR_TIME_LEFT = '' + CHAR_TIME_RIGHT = '' + COLOR_TIME_STRING = (-1, -1) + + # Tabs + COLOR_TAB_NORMAL = (-1, 0) + COLOR_TAB_NONEMPTY = (7, 4) + COLOR_TAB_SCROLLED = (5, 4) + COLOR_TAB_JOINED = (82, 4) + COLOR_TAB_CURRENT = (0, 13) + COLOR_TAB_COMPOSING = (7, 5) + COLOR_TAB_NEW_MESSAGE = (7, 5) + COLOR_TAB_HIGHLIGHT = (7, 3) + COLOR_TAB_PRIVATE = (7, 2) + COLOR_TAB_ATTENTION = (7, 1) + COLOR_TAB_DISCONNECTED = (7, 8) + + COLOR_VERTICAL_TAB_NORMAL = (4, -1) + COLOR_VERTICAL_TAB_NONEMPTY = (4, -1) + COLOR_VERTICAL_TAB_JOINED = (82, -1) + COLOR_VERTICAL_TAB_SCROLLED = (66, -1) + COLOR_VERTICAL_TAB_CURRENT = (7, 4) + COLOR_VERTICAL_TAB_NEW_MESSAGE = (5, -1) + COLOR_VERTICAL_TAB_COMPOSING = (5, -1) + COLOR_VERTICAL_TAB_HIGHLIGHT = (3, -1) + COLOR_VERTICAL_TAB_PRIVATE = (2, -1) + COLOR_VERTICAL_TAB_ATTENTION = (1, -1) + COLOR_VERTICAL_TAB_DISCONNECTED = (8, -1) + + # Nickname colors + # A list of colors randomly attributed to nicks in MUCs + # Setting more colors makes it harder to have two nicks with the same color, + # avoiding confusions. + LIST_COLOR_NICKNAMES = [ + (1, -1), (2, -1), (3, -1), (4, -1), (5, -1), (6, -1), (7, -1), + (8, -1), (9, -1), (10, -1), (11, -1), (12, -1), (13, -1), (14, -1) + ] + + # This is your own nickname + COLOR_OWN_NICK = (-1, -1) + + COLOR_LOG_MSG = (8, -1) + # This is for in-tab error messages + COLOR_ERROR_MSG = (9, -1, 'b') + # Status color + COLOR_STATUS_XA = (90, 0) + COLOR_STATUS_NONE = (4, 0) + COLOR_STATUS_DND = (1, 0) + COLOR_STATUS_AWAY = (3, 0) + COLOR_STATUS_CHAT = (2, 0) + COLOR_STATUS_UNAVAILABLE = (8, 0) + COLOR_STATUS_ONLINE = (4, 0) + + # Bars + COLOR_WARNING_PROMPT = (16, 1, 'b') + COLOR_INFORMATION_BAR = (7, 0) + COLOR_TOPIC_BAR = (7, 0) + COLOR_SCROLLABLE_NUMBER = (220, 4, 'b') + COLOR_SELECTED_ROW = (0, 13) + COLOR_PRIVATE_NAME = (-1, 4) + COLOR_CONVERSATION_NAME = (2, 0) + COLOR_CONVERSATION_RESOURCE = (121, 0) + COLOR_GROUPCHAT_NAME = (10, 0) + COLOR_COLUMN_HEADER = (36, 4) + COLOR_COLUMN_HEADER_SEL = (4, 36) + + # Strings for special messages (like join, quit, nick change, etc) + # Special messages + CHAR_JOIN = '--->' + CHAR_QUIT = '<---' + CHAR_KICK = '-!-' + CHAR_NEW_TEXT_SEPARATOR = ' ─' + CHAR_OK = '✔' + CHAR_ERROR = '✖' + CHAR_EMPTY = ' ' + CHAR_ACK_RECEIVED = CHAR_OK + CHAR_NACK = CHAR_ERROR + CHAR_COLUMN_ASC = ' ▲' + CHAR_COLUMN_DESC = ' ▼' + CHAR_ROSTER_ERROR = CHAR_ERROR + CHAR_ROSTER_TUNE = '♪' + CHAR_ROSTER_ASKED = '?' + CHAR_ROSTER_ACTIVITY = 'A' + CHAR_ROSTER_MOOD = 'M' + CHAR_ROSTER_GAMING = 'G' + CHAR_ROSTER_FROM = '←' + CHAR_ROSTER_BOTH = '↔' + CHAR_ROSTER_TO = '→' + CHAR_ROSTER_NONE = '⇹' + + COLOR_CHAR_ACK = (2, -1) + COLOR_CHAR_NACK = (1, -1) + + COLOR_ROSTER_GAMING = (6, -1) + COLOR_ROSTER_MOOD = (2, -1) + COLOR_ROSTER_ACTIVITY = (3, -1) + COLOR_ROSTER_TUNE = (6, -1) + COLOR_ROSTER_ERROR = (1, -1) + COLOR_ROSTER_SUBSCRIPTION = (-1, -1) + + COLOR_JOIN_CHAR = (4, -1) + COLOR_QUIT_CHAR = (1, -1) + COLOR_KICK_CHAR = (1, -1) + + # Vertical tab list color + COLOR_VERTICAL_TAB_NUMBER = (34, -1) + + # Info messages color (the part before the ">") + INFO_COLORS = { + 'info': (2, -1), + 'error': (1, -1, 'b'), + 'warning': (1, -1), + 'roster': (2, -1), + 'help': (10, -1), + 'headline': (11, -1, 'b'), + 'tune': (6, -1), + 'gaming': (6, -1), + 'mood': (5, -1), + 'activity': (3, -1), + 'default': (-1, -1), + } + +theme = CleanTheme() diff --git a/poezio/mam.py b/poezio/mam.py index 371b34dd..31ca2f0c 100644 --- a/poezio/mam.py +++ b/poezio/mam.py @@ -46,8 +46,9 @@ def make_line( tab: tabs.ChatTab, text: str, time: datetime, - nick: str, + jid: JID, identifier: str = '', + deterministic: bool = True, ) -> Message: """Adds a textual entry in the TextBuffer""" @@ -55,9 +56,8 @@ def make_line( time = time.replace(tzinfo=timezone.utc).astimezone(tz=None) time = time.replace(tzinfo=None) - deterministic = config.get_by_tabname('deterministic_nick_colors', tab.jid.bare) if isinstance(tab, tabs.MucTab): - nick = nick.split('/')[1] + nick = jid.resource user = tab.get_user_by_name(nick) if deterministic: if user: @@ -76,11 +76,12 @@ def make_line( color = xhtml.colors.get(color) color = (color, -1) else: - if nick.split('/')[0] == tab.core.xmpp.boundjid.bare: + if jid.bare == tab.core.xmpp.boundjid.bare: + nick = tab.core.own_nick color = get_theme().COLOR_OWN_NICK else: color = get_theme().COLOR_REMOTE_USER - nick = tab.get_nick() + nick = tab.get_nick() return Message( txt=text, identifier=identifier, @@ -133,7 +134,7 @@ def _parse_message(msg: SMessage) -> Dict: message = forwarded['stanza'] return { 'time': forwarded['delay']['stamp'], - 'nick': str(message['from']), + 'jid': message['from'], 'text': message['body'], 'identifier': message['origin-id'] } @@ -147,13 +148,17 @@ async def retrieve_messages(tab: tabs.ChatTab, msg_count = 0 msgs = [] to_add = [] + deterministic = config.get_by_tabname( + 'deterministic_nick_colors', + tab.jid.bare + ) try: async for rsm in results: for msg in rsm['mam']['results']: if msg['mam_result']['forwarded']['stanza'] \ .xml.find('{%s}%s' % ('jabber:client', 'body')) is not None: args = _parse_message(msg) - msgs.append(make_line(tab, **args)) + msgs.append(make_line(tab, deterministic=deterministic, **args)) for msg in reversed(msgs): to_add.append(msg) msg_count += 1 diff --git a/poezio/tabs/muctab.py b/poezio/tabs/muctab.py index 21e8997d..ace0df99 100644 --- a/poezio/tabs/muctab.py +++ b/poezio/tabs/muctab.py @@ -1504,7 +1504,8 @@ class MucTab(ChatTab): def on_close(self): super().on_close() - self.leave_room('') + if self.joined: + self.leave_room('') @command_args_parser.quoted(1, 1) def command_query(self, args): diff --git a/poezio/ui/render.py b/poezio/ui/render.py index c85d3cc5..633ac2a0 100644 --- a/poezio/ui/render.py +++ b/poezio/ui/render.py @@ -1,6 +1,9 @@ import curses -from datetime import datetime +from datetime import ( + datetime, + date, +) from functools import singledispatch from math import ceil, log10 from typing import ( @@ -235,7 +238,7 @@ class PreMessageHelpers: Write the date on the yth line of the window """ if time: - if history: + if history and time.date() != date.today(): format = LONG_FORMAT else: format = SHORT_FORMAT |