|
|
|
@ -5,16 +5,16 @@
|
|
|
|
|
# Copyright (C) 2024 John Mertz <git@john.me.tz>
|
|
|
|
|
#
|
|
|
|
|
# This library is free software; you can redistribute it and/or
|
|
|
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
# modify it under the terms of the GNU Affero Lesser General Public
|
|
|
|
|
# License as published by the Free Software Foundation; either
|
|
|
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
# version 3 of the License, or (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This library is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
# Lesser General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
# You should have received a copy of the GNU Affero Lesser General Public
|
|
|
|
|
# License along with this library; if not, write to the Free Software
|
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
#
|
|
|
|
@ -28,17 +28,91 @@ import urwid
|
|
|
|
|
class ConversationModel:
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.settings = {
|
|
|
|
|
"user_left": 1
|
|
|
|
|
}
|
|
|
|
|
self.data = {
|
|
|
|
|
"1234567890": ["Alice Bobson", { 'id': 1, 'sender':'1111111111', 'timestamp':100, 'msg': "hi"},{ 'id': 2, 'sender':'1234567890', 'timestamp':200, 'msg': "wassup!"}],
|
|
|
|
|
"1112223333": ["", { 'id': 1, 'sender':'1111111111', 'timestamp':1, 'msg': "hello"},{ 'id': 2, 'sender':'1112223333', 'timestamp':2, 'msg': "oh, hi"}],
|
|
|
|
|
"1234567890": [
|
|
|
|
|
"Alice Bobson",
|
|
|
|
|
{
|
|
|
|
|
'id': 1,
|
|
|
|
|
'sender':'1111111111',
|
|
|
|
|
'timestamp':100, 'msg': "hi"
|
|
|
|
|
},{
|
|
|
|
|
'id': 2,
|
|
|
|
|
'sender':'1234567890',
|
|
|
|
|
'timestamp':200,
|
|
|
|
|
'msg': "Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi."
|
|
|
|
|
},{
|
|
|
|
|
'id': 3,
|
|
|
|
|
'sender':'1234567890',
|
|
|
|
|
'timestamp':300,
|
|
|
|
|
'msg': "wassup!"
|
|
|
|
|
},{
|
|
|
|
|
'id': 4,
|
|
|
|
|
'sender':'1111111111',
|
|
|
|
|
'timestamp':400,
|
|
|
|
|
'msg': "Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi. Oh, Hi."
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"1112223333": [
|
|
|
|
|
"",
|
|
|
|
|
{
|
|
|
|
|
'id': 1,
|
|
|
|
|
'sender':'1111111111',
|
|
|
|
|
'timestamp':1,
|
|
|
|
|
'msg': "hello"
|
|
|
|
|
},{
|
|
|
|
|
'id': 2,
|
|
|
|
|
'sender':'1112223333',
|
|
|
|
|
'timestamp':2,
|
|
|
|
|
'msg': "oh, hi"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"0": [],
|
|
|
|
|
"1": [],
|
|
|
|
|
"2": [],
|
|
|
|
|
"3": [],
|
|
|
|
|
"4": [],
|
|
|
|
|
"5": [],
|
|
|
|
|
"6": [],
|
|
|
|
|
"7": [],
|
|
|
|
|
"8": [],
|
|
|
|
|
"9": [],
|
|
|
|
|
"10": [],
|
|
|
|
|
"11": [],
|
|
|
|
|
"12": [],
|
|
|
|
|
"13": [],
|
|
|
|
|
"14": [],
|
|
|
|
|
"15": [],
|
|
|
|
|
"16": [],
|
|
|
|
|
"17": [],
|
|
|
|
|
"18": [],
|
|
|
|
|
"19": [],
|
|
|
|
|
"20": [],
|
|
|
|
|
"21": [],
|
|
|
|
|
"22": [],
|
|
|
|
|
"23": [],
|
|
|
|
|
"24": [],
|
|
|
|
|
"25": [],
|
|
|
|
|
"26": [],
|
|
|
|
|
"27": [],
|
|
|
|
|
"28": [],
|
|
|
|
|
"29": [],
|
|
|
|
|
"30": [],
|
|
|
|
|
"31": [],
|
|
|
|
|
"32": [],
|
|
|
|
|
"33": [],
|
|
|
|
|
"34": [],
|
|
|
|
|
"35": [],
|
|
|
|
|
"36": [],
|
|
|
|
|
"37": [],
|
|
|
|
|
"38": [],
|
|
|
|
|
"39": [],
|
|
|
|
|
}
|
|
|
|
|
self.conversations = []
|
|
|
|
|
for key in self.data:
|
|
|
|
|
self.conversations.append(key)
|
|
|
|
|
self.current_conversation=self.conversations[0]
|
|
|
|
|
self.settings = {
|
|
|
|
|
"me_left": 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def get_conversations(self):
|
|
|
|
|
return self.conversations
|
|
|
|
@ -52,73 +126,90 @@ class ConversationModel:
|
|
|
|
|
last_time = 0
|
|
|
|
|
for m in d:
|
|
|
|
|
if not last_time:
|
|
|
|
|
if m != "":
|
|
|
|
|
lines.append(urwid.AttrMap(urwid.Text(m, urwid.CENTER), "header"))
|
|
|
|
|
else:
|
|
|
|
|
lines.append(urwid.Text(self.current_conversation, urwid.CENTER))
|
|
|
|
|
last_time=1
|
|
|
|
|
continue
|
|
|
|
|
if m['timestamp']-last_time >= 10:
|
|
|
|
|
lines.append(urwid.Text(str(m['timestamp']), urwid.CENTER))
|
|
|
|
|
last_time = m['timestamp']
|
|
|
|
|
if (m['sender'] == self.current_conversation) ^ (self.settings['me_left'] == 1):
|
|
|
|
|
lines.append(urwid.Padding(urwid.Text(m['msg'], urwid.RIGHT),left=10,right=1))
|
|
|
|
|
if (m['sender'] == self.current_conversation) ^ (self.settings['user_left'] == 1):
|
|
|
|
|
lines.append(
|
|
|
|
|
urwid.Columns(
|
|
|
|
|
[
|
|
|
|
|
urwid.Divider(" "),
|
|
|
|
|
(urwid.WEIGHT, 8, urwid.Padding(
|
|
|
|
|
urwid.LineBox(urwid.Text(m['msg'])), align='right', width=len(m['msg'])+2
|
|
|
|
|
)),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
lines.append(urwid.Padding(urwid.Text(m['msg'], urwid.LEFT),left=1,right=10))
|
|
|
|
|
lines.append(
|
|
|
|
|
urwid.Columns(
|
|
|
|
|
[
|
|
|
|
|
(urwid.WEIGHT, 8, urwid.Padding(
|
|
|
|
|
urwid.LineBox(urwid.Text(m['msg'])), width=len(m['msg'])+2
|
|
|
|
|
)),
|
|
|
|
|
urwid.Divider(" "),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
return lines
|
|
|
|
|
|
|
|
|
|
class ConversationView(urwid.WidgetWrap):
|
|
|
|
|
"""
|
|
|
|
|
A class responsible for providing the application's interface and
|
|
|
|
|
graph display.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
palette: typing.ClassVar[tuple[str, str, str, ...]] = [
|
|
|
|
|
palette = [
|
|
|
|
|
("body", "black", "light gray", "standout"),
|
|
|
|
|
("logo_red", "dark red", "light gray", "standout"),
|
|
|
|
|
("logo_black", "black", "light gray", "standout"),
|
|
|
|
|
("header", "white", "dark red", "bold"),
|
|
|
|
|
("screen edge", "light blue", "dark cyan"),
|
|
|
|
|
("main shadow", "dark gray", "black"),
|
|
|
|
|
("line", "black", "light gray", "standout"),
|
|
|
|
|
("bg background", "light gray", "black"),
|
|
|
|
|
("bg 1", "black", "dark blue", "standout"),
|
|
|
|
|
("bg 1 smooth", "dark blue", "black"),
|
|
|
|
|
("bg 2", "black", "dark cyan", "standout"),
|
|
|
|
|
("bg 2 smooth", "dark cyan", "black"),
|
|
|
|
|
("button normal", "light gray", "dark blue", "standout"),
|
|
|
|
|
("button select", "white", "dark green"),
|
|
|
|
|
("line", "black", "light gray", "standout"),
|
|
|
|
|
("pg normal", "white", "black", "standout"),
|
|
|
|
|
("pg complete", "white", "dark magenta"),
|
|
|
|
|
("pg smooth", "dark magenta", "black"),
|
|
|
|
|
("footer", "black", "dark cyan"),
|
|
|
|
|
("sidebar", "dark gray", "black"),
|
|
|
|
|
("buttn", "white", "dark green"),
|
|
|
|
|
("buttnf", "white", "light green", "bold"),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
graph_samples_per_bar = 10
|
|
|
|
|
graph_num_bars = 5
|
|
|
|
|
graph_offset_per_second = 5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, controller):
|
|
|
|
|
self.controller = controller
|
|
|
|
|
def __init__(self, model):
|
|
|
|
|
self.model = model
|
|
|
|
|
self.started = True
|
|
|
|
|
self.offset = 0
|
|
|
|
|
self.last_offset = None
|
|
|
|
|
self.current_conversation=None
|
|
|
|
|
super().__init__(self.main_window())
|
|
|
|
|
|
|
|
|
|
def logo(self):
|
|
|
|
|
return [
|
|
|
|
|
urwid.Divider(" ", top=10),
|
|
|
|
|
urwid.Padding(
|
|
|
|
|
urwid.Pile([
|
|
|
|
|
urwid.Text([("logo_red","┌─┐ ┌─┐┌──────┐┌─┐┌─────┐"),("logo_black","┌───────┐┌──────┐")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_red","│ │ │ ││ ┌──┐ │└─┘└───┐ │"),("logo_black","│ ┌───┐ ││ ┌────┘")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_red","│ └┐┌┘ ││ │ │ │┌─┐┌───┘ │"),("logo_black","│ │┌─┐│ ││ └┐┌──┐")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_red","└┐ └┘ ┌┘│ │ │ ││ ││ ┌───┘"),("logo_black","│ ││ ││ │└──┘└┐ │")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_red"," └┐ ┌┘ │ └──┘ ││ ││ │"),("logo_black"," ┌─┐│ ││ ││ │┌────┘ │")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_red"," └──┘ └──────┘└─┘└─┘"),("logo_black"," └─┘└─┘└─┘└─┘└──────┘")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_black","┌─────┐┌───────┐┌─────┐"),("logo_red"," ┌─────┐┌─┐ ┌─┐┌───┐")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_black","│ ┌───┘│ ┌┐ ┌┐ ││ ┌───┘"),("logo_red"," └─┐ ┌─┘│ │ │ │└┐ ┌┘")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_black","│ └───┐│ ││ ││ ││ └───┐┌─┐"),("logo_red","│ │ │ │ │ │ │ │ ")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_black","└───┐ ││ ││ ││ │└───┐ │└─┘"),("logo_red","│ │ │ │ │ │ │ │ ")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_black","┌───┘ ││ ││ ││ │┌───┘ │"),("logo_red"," │ │ │ └─┘ │┌┘ └┐")],align=urwid.CENTER),
|
|
|
|
|
urwid.Text([("logo_black","└─────┘└─┘└─┘└─┘└─────┘"),("logo_red"," └─┘ └─────┘└───┘")],align=urwid.CENTER),
|
|
|
|
|
]),
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
def update_conversation(self, force_update=False):
|
|
|
|
|
return urwid.SimpleListWalker(self.controller.get_messages())
|
|
|
|
|
return self.model.get_messages()
|
|
|
|
|
|
|
|
|
|
def on_conversation_button(self, button, state):
|
|
|
|
|
"""Notify the controller of a new conversation setting."""
|
|
|
|
|
"""Notify the model of a new conversation setting."""
|
|
|
|
|
self.scroll_to_bottom()
|
|
|
|
|
return 1
|
|
|
|
|
if state:
|
|
|
|
|
# The new conversation is the label of the button
|
|
|
|
|
self.controller.set_conversation(button.get_label().split("\n")[0])
|
|
|
|
|
self.model.set_conversation(conversation)
|
|
|
|
|
self.graph = self.conversation()
|
|
|
|
|
self.model.set_conversation(button.get_label().split("\n")[0])
|
|
|
|
|
self.model.set_conversation(self.conversation)
|
|
|
|
|
self.chat = self.conversation()
|
|
|
|
|
self.view = urwid.Frame(
|
|
|
|
|
urwid.AttrMap(self.graph, "body"),
|
|
|
|
|
urwid.AttrMap(self.chat, "body"),
|
|
|
|
|
footer=self.send
|
|
|
|
|
)
|
|
|
|
|
self.last_offset = None
|
|
|
|
|
|
|
|
|
|
def on_conversation_change(self, m):
|
|
|
|
|
"""Handle external conversation change by updating radio buttons."""
|
|
|
|
@ -126,18 +217,17 @@ class ConversationView(urwid.WidgetWrap):
|
|
|
|
|
if rb.base_widget.label == m:
|
|
|
|
|
rb.base_widget.set_state(True, do_callback=False)
|
|
|
|
|
break
|
|
|
|
|
self.last_offset = None
|
|
|
|
|
conversation = self.controller.get_conversations()[0]
|
|
|
|
|
|
|
|
|
|
def bar_graph(self, smooth=False):
|
|
|
|
|
satt = None
|
|
|
|
|
if smooth:
|
|
|
|
|
satt = {(1, 0): "bg 1 smooth", (2, 0): "bg 2 smooth"}
|
|
|
|
|
w = urwid.BarGraph(["bg background", "bg 1", "bg 2"], satt=satt)
|
|
|
|
|
return w
|
|
|
|
|
if m != "":
|
|
|
|
|
self.header = urwid.Text(m, urwid.CENTER)
|
|
|
|
|
else:
|
|
|
|
|
self.header = urwid.Text(self.current_conversation, urwid.CENTER)
|
|
|
|
|
conversation = self.model.get_conversations()[0]
|
|
|
|
|
|
|
|
|
|
def conversation(self):
|
|
|
|
|
return urwid.ListBox(self.update_conversation())
|
|
|
|
|
if self.current_conversation == None:
|
|
|
|
|
return self.logo()
|
|
|
|
|
else:
|
|
|
|
|
return self.model.get_messages()
|
|
|
|
|
|
|
|
|
|
def button(self, t, fn):
|
|
|
|
|
w = urwid.Button(t, fn)
|
|
|
|
@ -157,7 +247,7 @@ class ConversationView(urwid.WidgetWrap):
|
|
|
|
|
raise urwid.ExitMainLoop()
|
|
|
|
|
|
|
|
|
|
def conversation_selection(self):
|
|
|
|
|
conversations = self.controller.get_conversations()
|
|
|
|
|
conversations = self.model.get_conversations()
|
|
|
|
|
# setup conversation radio buttons
|
|
|
|
|
self.conversation_buttons = []
|
|
|
|
|
group = []
|
|
|
|
@ -177,77 +267,105 @@ class ConversationView(urwid.WidgetWrap):
|
|
|
|
|
def send_update(self, field, msg):
|
|
|
|
|
field=msg.edit_text
|
|
|
|
|
|
|
|
|
|
def scroll_to_bottom(self):
|
|
|
|
|
self.scrollable.set_scrollpos(-1)
|
|
|
|
|
|
|
|
|
|
def main_window(self):
|
|
|
|
|
#self.graph = self.bar_graph()
|
|
|
|
|
self.graph = self.conversation()
|
|
|
|
|
self.send_content = "preset"
|
|
|
|
|
self.send_box = urwid.Edit("", self.send_content, multiline=True)
|
|
|
|
|
urwid.connect_signal(self.send_box, 'change', self.send_update(self.send_content,self.send_box))
|
|
|
|
|
self.chat = self.conversation()
|
|
|
|
|
self.send_content = ""
|
|
|
|
|
self.send_edit = urwid.Edit("", self.send_content, multiline=True)
|
|
|
|
|
self.send_box = urwid.Padding(self.send_edit, left=1, right=1)
|
|
|
|
|
urwid.connect_signal(self.send_edit, 'change', self.send_update(self.send_content,self.send_edit))
|
|
|
|
|
self.send_button = urwid.Padding(
|
|
|
|
|
urwid.AttrMap(
|
|
|
|
|
urwid.Button(
|
|
|
|
|
"SEND", self.send_message(self.send_box), align=urwid.CENTER
|
|
|
|
|
),
|
|
|
|
|
"buttn", "buttnf"
|
|
|
|
|
urwid.AttrMap(
|
|
|
|
|
urwid.Button(
|
|
|
|
|
"SEND", self.send_message(self.send_edit), align=urwid.CENTER
|
|
|
|
|
),
|
|
|
|
|
"buttn", "buttnf"
|
|
|
|
|
),
|
|
|
|
|
left=0,
|
|
|
|
|
right=0
|
|
|
|
|
)
|
|
|
|
|
self.char_count="0/140";
|
|
|
|
|
self.send_pile = urwid.Pile([
|
|
|
|
|
self.send_button,
|
|
|
|
|
urwid.Text(self.char_count, align=urwid.CENTER)
|
|
|
|
|
])
|
|
|
|
|
self.send = urwid.Columns([
|
|
|
|
|
(urwid.WEIGHT, 8, self.send_box),
|
|
|
|
|
self.send_button,
|
|
|
|
|
self.send_pile,
|
|
|
|
|
])
|
|
|
|
|
self.view = urwid.Frame(
|
|
|
|
|
urwid.AttrMap(self.graph, "body"),
|
|
|
|
|
footer=self.send
|
|
|
|
|
self.header = urwid.Text("VoIP.ms SMS TUI", urwid.CENTER)
|
|
|
|
|
self.scrollable = urwid.Scrollable(urwid.Pile(self.chat))
|
|
|
|
|
self.sb_chat = urwid.ScrollBar(self.scrollable, trough_char=urwid.ScrollBar.Symbols.LITE_SHADE)
|
|
|
|
|
self.view = urwid.Pile([
|
|
|
|
|
('pack', urwid.AttrMap(self.header, "header")),
|
|
|
|
|
urwid.AttrMap(self.sb_chat, "body"),
|
|
|
|
|
('pack', urwid.AttrMap(self.send, "footer")),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
self.scroll_to_bottom()
|
|
|
|
|
selection = self.conversation_selection()
|
|
|
|
|
sb_selection = urwid.ScrollBar(selection, trough_char=urwid.ScrollBar.Symbols.LITE_SHADE)
|
|
|
|
|
new_conversation = urwid.AttrMap(
|
|
|
|
|
urwid.Button(
|
|
|
|
|
"New", self.send_message(self.send_edit), align=urwid.CENTER
|
|
|
|
|
),
|
|
|
|
|
"buttn", "buttnf"
|
|
|
|
|
)
|
|
|
|
|
settings = urwid.AttrMap(
|
|
|
|
|
urwid.Button(
|
|
|
|
|
"Settings", self.send_message(self.send_edit), align=urwid.CENTER
|
|
|
|
|
),
|
|
|
|
|
"buttn", "buttnf"
|
|
|
|
|
)
|
|
|
|
|
c = urwid.Pile([
|
|
|
|
|
('pack',new_conversation),
|
|
|
|
|
sb_selection,
|
|
|
|
|
('pack',settings),
|
|
|
|
|
])
|
|
|
|
|
w = urwid.Columns(
|
|
|
|
|
[
|
|
|
|
|
urwid.AttrMap(c, "sidebar"),
|
|
|
|
|
(urwid.WEIGHT, 3, self.view)
|
|
|
|
|
],
|
|
|
|
|
dividechars=0, focus_column=0
|
|
|
|
|
)
|
|
|
|
|
c = self.conversation_selection()
|
|
|
|
|
w = urwid.Columns([c, (urwid.WEIGHT, 3, self.view)], dividechars=0, focus_column=0)
|
|
|
|
|
w = urwid.AttrMap(w, "body")
|
|
|
|
|
return w
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SMSController:
|
|
|
|
|
"""
|
|
|
|
|
A class responsible for setting up the model and view and running
|
|
|
|
|
the application.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.model = ConversationModel()
|
|
|
|
|
self.view = ConversationView(self)
|
|
|
|
|
# use the first conversation as the default
|
|
|
|
|
conversation = self.get_conversations()[0]
|
|
|
|
|
self.model.set_conversation(conversation)
|
|
|
|
|
# update the view
|
|
|
|
|
self.view.on_conversation_change(conversation)
|
|
|
|
|
self.view.update_conversation(True)
|
|
|
|
|
|
|
|
|
|
def get_conversations(self):
|
|
|
|
|
"""Allow our view access to the list of conversations."""
|
|
|
|
|
return self.model.get_conversations()
|
|
|
|
|
|
|
|
|
|
def set_conversation(self, m) -> None:
|
|
|
|
|
"""Allow our view to set the conversation."""
|
|
|
|
|
self.model.set_conversation(m)
|
|
|
|
|
self.view.update_conversation(True)
|
|
|
|
|
|
|
|
|
|
def get_messages(self):
|
|
|
|
|
"""Provide data to our view for the graph."""
|
|
|
|
|
return self.model.get_messages()
|
|
|
|
|
|
|
|
|
|
def unhandled(self, key: str | tuple[str, int, int, int]) -> None:
|
|
|
|
|
if key == "F8":
|
|
|
|
|
self.exit_program
|
|
|
|
|
|
|
|
|
|
def main(self):
|
|
|
|
|
urwid.MainLoop(self.view, self.view.palette, unhandled_input=self.unhandled).run()
|
|
|
|
|
self.loop.run()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
SMSController().main()
|
|
|
|
|
|
|
|
|
|
def get_conversations():
|
|
|
|
|
return model.get_conversations()
|
|
|
|
|
|
|
|
|
|
def set_conversation(m) -> None:
|
|
|
|
|
model.set_conversation(m)
|
|
|
|
|
view.update_conversation(True)
|
|
|
|
|
|
|
|
|
|
def get_messages():
|
|
|
|
|
return model.get_messages()
|
|
|
|
|
|
|
|
|
|
def unhandled( key: str | tuple[str, int, int, int]) -> None:
|
|
|
|
|
if key == "F8":
|
|
|
|
|
exit_program
|
|
|
|
|
|
|
|
|
|
model = ConversationModel()
|
|
|
|
|
view = ConversationView(model)
|
|
|
|
|
# use the first conversation as the default
|
|
|
|
|
conversation = get_conversations()[0]
|
|
|
|
|
model.set_conversation(conversation)
|
|
|
|
|
# update the view
|
|
|
|
|
view.on_conversation_change(conversation)
|
|
|
|
|
view.update_conversation(True)
|
|
|
|
|
urwid.MainLoop(view, view.palette, unhandled_input=unhandled).run()
|
|
|
|
|
view.scroll_to_bottom()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def setup():
|
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|
|
|
|
|
setup()
|
|
|
|
|