Clean up room widget and add nick list
This commit is contained in:
parent
d3cd63b67e
commit
d7f6d5a536
1 changed files with 88 additions and 50 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from enum import Enum
|
||||||
from typing import Any, Awaitable, Callable, List, Optional, Tuple, TypeVar
|
from typing import Any, Awaitable, Callable, List, Optional, Tuple, TypeVar
|
||||||
|
|
||||||
import urwid
|
import urwid
|
||||||
|
|
||||||
import yaboli
|
import yaboli
|
||||||
|
|
||||||
from ..attributed_text_widget import ATWidget
|
from ..attributed_text_widget import ATWidget
|
||||||
|
|
@ -14,6 +14,7 @@ from ..markup import AT, AttributedText, Attributes
|
||||||
from .edit_widgets import EditWidget
|
from .edit_widgets import EditWidget
|
||||||
from .euph_config import EuphConfig
|
from .euph_config import EuphConfig
|
||||||
from .euph_renderer import EuphRenderer
|
from .euph_renderer import EuphRenderer
|
||||||
|
from .nick_list_widget import NickListWidget
|
||||||
|
|
||||||
__all__ = ["RoomWidget"]
|
__all__ = ["RoomWidget"]
|
||||||
|
|
||||||
|
|
@ -129,23 +130,33 @@ class RoomLayout(urwid.WidgetWrap):
|
||||||
string = self._edit_separator * tree_width
|
string = self._edit_separator * tree_width
|
||||||
return AT(string, attributes=self._border_attrs)
|
return AT(string, attributes=self._border_attrs)
|
||||||
|
|
||||||
def set_edit_visible(self, visible: bool):
|
def set_edit_visible(self, visible: bool) -> None:
|
||||||
if visible:
|
if visible:
|
||||||
self._left_wrap._w = self._edit_pile
|
self._left_wrap._w = self._edit_pile
|
||||||
else:
|
else:
|
||||||
self._left_wrap._w = self._tree
|
self._left_wrap._w = self._tree
|
||||||
|
|
||||||
def focus_on_edit(self):
|
def focus_on_edit(self) -> None:
|
||||||
self._edit_pile.focus_position = 2
|
self._edit_pile.focus_position = 2
|
||||||
self._columns.focus_position = 0
|
self._columns.focus_position = 0
|
||||||
|
|
||||||
def focus_on_tree(self):
|
def focus_on_tree(self) -> None:
|
||||||
self._edit_pile.focus_position = 0
|
self._edit_pile.focus_position = 0
|
||||||
self._columns.focus_position = 0
|
self._columns.focus_position = 0
|
||||||
|
|
||||||
def focus_on_user_list(self):
|
def focus_on_nick_list(self) -> None:
|
||||||
self._columns.focus_position = 2
|
self._columns.focus_position = 2
|
||||||
|
|
||||||
|
class UiMode(Enum):
|
||||||
|
|
||||||
|
CONNECTING = "connecting"
|
||||||
|
CONNECTION_FAILED = "connection failed"
|
||||||
|
SETTING_PASSWORD = "setting password"
|
||||||
|
AUTHENTICATING = "authenticating"
|
||||||
|
SETTING_NICK = "setting nick"
|
||||||
|
VIEWING = "viewing"
|
||||||
|
EDITING = "editing"
|
||||||
|
|
||||||
class RoomWidget(urwid.WidgetWrap):
|
class RoomWidget(urwid.WidgetWrap):
|
||||||
"""
|
"""
|
||||||
The RoomWidget connects to and displays a single yaboli room.
|
The RoomWidget connects to and displays a single yaboli room.
|
||||||
|
|
@ -159,11 +170,6 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
event
|
event
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CONNECTING = "connecting"
|
|
||||||
CONNECTION_FAILED = "connection_failed"
|
|
||||||
VIEWING = "viewing"
|
|
||||||
EDITING = "editing"
|
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
roomname: str,
|
roomname: str,
|
||||||
config: EuphConfig,
|
config: EuphConfig,
|
||||||
|
|
@ -172,17 +178,24 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
|
|
||||||
self.c = config
|
self.c = config
|
||||||
|
|
||||||
if log_amount < 1:
|
|
||||||
raise ValueError() # TODO add better text
|
|
||||||
self._log_amount = log_amount
|
self._log_amount = log_amount
|
||||||
|
if self._log_amount < 1:
|
||||||
|
raise ValueError("log request amount must be at least 1")
|
||||||
|
|
||||||
self._mode: str
|
self._mode: UiMode
|
||||||
self._requesting_logs = False
|
self._requesting_logs = False
|
||||||
self._hit_top_of_supply = False
|
self._hit_top_of_supply = False
|
||||||
|
|
||||||
self._room = yaboli.Room(roomname)
|
self._room = yaboli.Room(roomname)
|
||||||
|
|
||||||
|
self._room.register_event("connected", self.on_connected)
|
||||||
self._room.register_event("snapshot", self.on_snapshot)
|
self._room.register_event("snapshot", self.on_snapshot)
|
||||||
self._room.register_event("send", self.on_send)
|
self._room.register_event("send", self.on_send)
|
||||||
|
self._room.register_event("join", self.on_join)
|
||||||
|
self._room.register_event("part", self.on_part)
|
||||||
|
self._room.register_event("nick", self.on_nick)
|
||||||
|
self._room.register_event("edit", self.on_edit)
|
||||||
|
self._room.register_event("disconnect", self.on_disconnect)
|
||||||
|
|
||||||
self._supply = InMemorySupply[Message]()
|
self._supply = InMemorySupply[Message]()
|
||||||
self._renderer = self._create_euph_renderer()
|
self._renderer = self._create_euph_renderer()
|
||||||
|
|
@ -297,7 +310,12 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
return urwid.Edit(multiline=True)
|
return urwid.Edit(multiline=True)
|
||||||
|
|
||||||
def _create_nick_list_widget(self) -> Any:
|
def _create_nick_list_widget(self) -> Any:
|
||||||
return urwid.SolidFill("n")
|
return NickListWidget(
|
||||||
|
heading_attrs={"style": self.c.nick_list_heading_style},
|
||||||
|
counter_attrs={"style": self.c.nick_list_counter_style},
|
||||||
|
nick_attrs={"style": self.c.nick_style},
|
||||||
|
own_nick_attrs={"style": self.c.own_nick_style},
|
||||||
|
)
|
||||||
|
|
||||||
def _create_room_layout_widget(self,
|
def _create_room_layout_widget(self,
|
||||||
room_name: Any,
|
room_name: Any,
|
||||||
|
|
@ -336,50 +354,42 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
|
|
||||||
## UI mode and mode switching
|
## UI mode and mode switching
|
||||||
|
|
||||||
CONNECTING = "connecting"
|
|
||||||
CONNECTION_FAILED = "connection_failed"
|
|
||||||
SETTING_PASSWORD = "setting_password"
|
|
||||||
AUTHENTICATING = "authenticating"
|
|
||||||
SETTING_NICK = "setting_nick"
|
|
||||||
VIEWING = "viewing"
|
|
||||||
EDITING = "editing"
|
|
||||||
|
|
||||||
def switch_connecting(self) -> None:
|
def switch_connecting(self) -> None:
|
||||||
self._w = self._connecting
|
self._w = self._connecting
|
||||||
self._mode = self.CONNECTING
|
self._mode = UiMode.CONNECTING
|
||||||
|
|
||||||
def switch_connection_failed(self) -> None:
|
def switch_connection_failed(self) -> None:
|
||||||
self._w = self._connection_failed
|
self._w = self._connection_failed
|
||||||
self._mode = self.CONNECTION_FAILED
|
self._mode = UiMode.CONNECTION_FAILED
|
||||||
|
|
||||||
def switch_setting_password(self) -> None:
|
def switch_setting_password(self) -> None:
|
||||||
self._w = self._overlay
|
self._w = self._overlay
|
||||||
self._overlay.set_top(self._edit_password)
|
self._overlay.set_top(self._edit_password)
|
||||||
self._mode = self.SETTING_PASSWORD
|
self._mode = UiMode.SETTING_PASSWORD
|
||||||
|
|
||||||
def switch_authenticating(self) -> None:
|
def switch_authenticating(self) -> None:
|
||||||
self._w = self._overlay
|
self._w = self._overlay
|
||||||
self._overlay.set_top(self._authenticating)
|
self._overlay.set_top(self._authenticating)
|
||||||
self._mode = self.AUTHENTICATING
|
self._mode = UiMode.AUTHENTICATING
|
||||||
|
|
||||||
def switch_setting_nick(self) -> None:
|
def switch_setting_nick(self) -> None:
|
||||||
self._w = self._overlay
|
self._w = self._overlay
|
||||||
self._box.original_widget = self._edit_nick
|
self._box.original_widget = self._edit_nick
|
||||||
self._edit_nick.text = self._room.session.nick
|
self._edit_nick.text = self._room.session.nick
|
||||||
self.update_edit_nick()
|
self.update_edit_nick()
|
||||||
self._mode = self.SETTING_NICK
|
self._mode = UiMode.SETTING_NICK
|
||||||
|
|
||||||
def switch_view(self) -> None:
|
def switch_view(self) -> None:
|
||||||
self._w = self._layout
|
self._w = self._layout
|
||||||
self._layout.set_edit_visible(False)
|
self._layout.set_edit_visible(False)
|
||||||
self._layout.focus_on_tree()
|
self._layout.focus_on_tree()
|
||||||
self._mode = self.VIEWING
|
self._mode = UiMode.VIEWING
|
||||||
|
|
||||||
def switch_edit(self) -> None:
|
def switch_edit(self) -> None:
|
||||||
self._w = self._layout
|
self._w = self._layout
|
||||||
self._layout.set_edit_visible(True)
|
self._layout.set_edit_visible(True)
|
||||||
self._layout.focus_on_edit()
|
self._layout.focus_on_edit()
|
||||||
self._mode = self.EDITING
|
self._mode = UiMode.EDITING
|
||||||
|
|
||||||
# Updating various parts of the UI
|
# Updating various parts of the UI
|
||||||
|
|
||||||
|
|
@ -388,12 +398,15 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
|
|
||||||
def update_nick_list(self) -> None:
|
def update_nick_list(self) -> None:
|
||||||
# Ensure that self._room.session and self._room.users exist
|
# Ensure that self._room.session and self._room.users exist
|
||||||
if self._mode not in {self.SETTING_NICK, self.VIEWING, self.EDITING}:
|
allowed = {UiMode.SETTING_NICK, UiMode.VIEWING, UiMode.EDITING}
|
||||||
|
if self._mode not in allowed:
|
||||||
return
|
return
|
||||||
|
|
||||||
#self._nick_list.update(self._room.session, self._room.users)
|
# Automatically rerenders
|
||||||
|
self._nick_list.session = self._room.session
|
||||||
|
self._nick_list.users = self._room.users
|
||||||
|
|
||||||
def update_edit_nick(self):
|
def update_edit_nick(self) -> None:
|
||||||
width = self._edit_nick.width
|
width = self._edit_nick.width
|
||||||
self._overlay.set_overlay_parameters(
|
self._overlay.set_overlay_parameters(
|
||||||
align=urwid.CENTER,
|
align=urwid.CENTER,
|
||||||
|
|
@ -403,15 +416,15 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
)
|
)
|
||||||
self._overlay._invalidate()
|
self._overlay._invalidate()
|
||||||
|
|
||||||
# Reacting to changes
|
def change_own_nick(self) -> None:
|
||||||
|
|
||||||
def own_nick_change(self):
|
|
||||||
self._renderer.nick = self._room.session.nick
|
self._renderer.nick = self._room.session.nick
|
||||||
self._tree.invalidate_all()
|
self._tree.invalidate_all()
|
||||||
self.update_tree()
|
self.update_tree()
|
||||||
|
|
||||||
|
self._nick_list.session = self._room.session
|
||||||
self.update_nick_list()
|
self.update_nick_list()
|
||||||
|
|
||||||
def receive_message(self, msg: yaboli.Message):
|
def receive_message(self, msg: yaboli.Message) -> None:
|
||||||
self._supply.add(Message(
|
self._supply.add(Message(
|
||||||
msg.message_id,
|
msg.message_id,
|
||||||
msg.parent_id,
|
msg.parent_id,
|
||||||
|
|
@ -434,7 +447,7 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
return canvas
|
return canvas
|
||||||
|
|
||||||
def keypress(self, size: Tuple[int, int], key: str) -> Optional[str]:
|
def keypress(self, size: Tuple[int, int], key: str) -> Optional[str]:
|
||||||
if self._mode == self.VIEWING:
|
if self._mode == UiMode.VIEWING:
|
||||||
if key in {"enter", "meta enter"} and not self._room.session.nick:
|
if key in {"enter", "meta enter"} and not self._room.session.nick:
|
||||||
self.switch_setting_nick()
|
self.switch_setting_nick()
|
||||||
elif key == "enter":
|
elif key == "enter":
|
||||||
|
|
@ -452,7 +465,7 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
else:
|
else:
|
||||||
return super().keypress(size, key)
|
return super().keypress(size, key)
|
||||||
|
|
||||||
elif self._mode == self.EDITING:
|
elif self._mode == UiMode.EDITING:
|
||||||
if key == "enter":
|
if key == "enter":
|
||||||
if self._edit.edit_text:
|
if self._edit.edit_text:
|
||||||
self.send(self._edit.edit_text, self._tree.cursor_id)
|
self.send(self._edit.edit_text, self._tree.cursor_id)
|
||||||
|
|
@ -464,7 +477,7 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
else:
|
else:
|
||||||
return super().keypress(size, key)
|
return super().keypress(size, key)
|
||||||
|
|
||||||
elif self._mode == self.SETTING_NICK:
|
elif self._mode == UiMode.SETTING_NICK:
|
||||||
if key == "enter":
|
if key == "enter":
|
||||||
if self._edit_nick.text:
|
if self._edit_nick.text:
|
||||||
self.nick(self._edit_nick.text)
|
self.nick(self._edit_nick.text)
|
||||||
|
|
@ -485,37 +498,62 @@ class RoomWidget(urwid.WidgetWrap):
|
||||||
|
|
||||||
# Reacting to euph events
|
# Reacting to euph events
|
||||||
|
|
||||||
async def on_snapshot(self, messages: List[yaboli.Message]):
|
async def on_connected(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def on_snapshot(self, messages: List[yaboli.LiveMessage]) -> None:
|
||||||
for message in messages:
|
for message in messages:
|
||||||
self.receive_message(message)
|
self.receive_message(message)
|
||||||
self.update_tree()
|
|
||||||
|
|
||||||
async def on_send(self, message: yaboli.Message):
|
self.update_nick_list()
|
||||||
|
|
||||||
|
async def on_send(self, message: yaboli.LiveMessage) -> None:
|
||||||
self.receive_message(message)
|
self.receive_message(message)
|
||||||
self.update_tree()
|
|
||||||
|
async def on_join(self, user: yaboli.LiveSession) -> None:
|
||||||
|
self.update_nick_list()
|
||||||
|
|
||||||
|
async def on_part(self, user: yaboli.LiveSession) -> None:
|
||||||
|
self.update_nick_list()
|
||||||
|
|
||||||
|
async def on_nick(self,
|
||||||
|
user: yaboli.LiveSession,
|
||||||
|
from_: str,
|
||||||
|
to: str,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
self.update_nick_list()
|
||||||
|
|
||||||
|
async def on_edit(self, message: yaboli.LiveMessage) -> None:
|
||||||
|
self.receive_message(message)
|
||||||
|
|
||||||
|
async def on_disconnect(self, reason: str) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
# Euph actions
|
# Euph actions
|
||||||
|
|
||||||
@synchronous
|
@synchronous
|
||||||
async def request_logs(self):
|
async def request_logs(self) -> None:
|
||||||
oldest_id = self._supply.oldest_id()
|
oldest_id = self._supply.oldest_id()
|
||||||
if oldest_id is not None:
|
if oldest_id is not None:
|
||||||
messages = await self._room.log(self._log_amount, oldest_id)
|
messages = await self._room.log(self._log_amount, oldest_id)
|
||||||
|
|
||||||
|
if len(messages) == 0:
|
||||||
|
self._hit_top_of_supply = True
|
||||||
|
|
||||||
for message in messages:
|
for message in messages:
|
||||||
self.receive_message(message)
|
self.receive_message(message)
|
||||||
self.update_tree()
|
|
||||||
|
|
||||||
self._requesting_logs = False
|
self._requesting_logs = False
|
||||||
|
|
||||||
@synchronous
|
@synchronous
|
||||||
async def nick(self, nick: str):
|
async def nick(self, nick: str) -> None:
|
||||||
new_nick = await self._room.nick(nick)
|
await self._room.nick(nick)
|
||||||
self.own_nick_change()
|
self.change_own_nick()
|
||||||
|
|
||||||
@synchronous
|
@synchronous
|
||||||
async def send(self, content: str, parent_id: Optional[str]):
|
async def send(self, content: str, parent_id: Optional[str]) -> None:
|
||||||
message = await self._room.send(content, parent_id=parent_id)
|
message = await self._room.send(content, parent_id=parent_id)
|
||||||
self.receive_message(message)
|
self.receive_message(message)
|
||||||
self.update_tree()
|
|
||||||
|
|
||||||
urwid.register_signal(RoomWidget, ["close"])
|
urwid.register_signal(RoomWidget, ["close"])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue