Home Timeline working with image viewing

This commit is contained in:
jfm 2024-05-02 20:22:35 +02:00
parent 2be82fb169
commit 661aee6e14
6 changed files with 498 additions and 46 deletions

View File

@ -13,6 +13,7 @@ textual = "*"
pydantic = "*" pydantic = "*"
pymastodon = {version="*", index="moerks"} pymastodon = {version="*", index="moerks"}
markdownify = "*" markdownify = "*"
pillow = "*"
[dev-packages] [dev-packages]

89
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "0ff61328a9369d70ce7094e72d664495cbce99af0e1d0a0f6a81528b966a9ec5" "sha256": "0c92ab9c7331b4c4ef3202f85b81a76f25fc007fb7d6cbf33eb6bc4882e1929d"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -199,6 +199,81 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==0.1.2" "version": "==0.1.2"
}, },
"pillow": {
"hashes": [
"sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c",
"sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2",
"sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb",
"sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d",
"sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa",
"sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3",
"sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1",
"sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a",
"sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd",
"sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8",
"sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999",
"sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599",
"sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936",
"sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375",
"sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d",
"sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b",
"sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60",
"sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572",
"sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3",
"sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced",
"sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f",
"sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b",
"sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19",
"sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f",
"sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d",
"sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383",
"sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795",
"sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355",
"sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57",
"sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09",
"sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b",
"sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462",
"sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf",
"sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f",
"sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a",
"sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad",
"sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9",
"sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d",
"sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45",
"sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994",
"sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d",
"sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338",
"sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463",
"sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451",
"sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591",
"sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c",
"sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd",
"sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32",
"sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9",
"sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf",
"sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5",
"sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828",
"sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3",
"sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5",
"sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2",
"sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b",
"sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2",
"sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475",
"sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3",
"sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb",
"sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef",
"sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015",
"sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002",
"sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170",
"sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84",
"sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57",
"sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f",
"sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27",
"sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"
],
"index": "pypi",
"version": "==10.3.0"
},
"pydantic": { "pydantic": {
"hashes": [ "hashes": [
"sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5", "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5",
@ -302,11 +377,11 @@
}, },
"pymastodon": { "pymastodon": {
"hashes": [ "hashes": [
"sha256:290e12ba161a4c87374ac55a437ee78edf3d0d1dc6d65ab653ceebdd0cba2dfb", "sha256:3c4c054e65368c7c4786fc48d97a64efcced3c6eb95084ee852ccccfc8d04d81",
"sha256:32526b5da307ad6f64ca5ff028437d23de07e4237e04fc0111ca8522b6f89fd5" "sha256:7ae4df3e669a749f257a5cd8c6866d9331cf81412f31539dda31e17748493452"
], ],
"index": "moerks", "index": "moerks",
"version": "==0.8.0" "version": "==0.16.0"
}, },
"requests": { "requests": {
"hashes": [ "hashes": [
@ -342,11 +417,11 @@
}, },
"textual": { "textual": {
"hashes": [ "hashes": [
"sha256:5c8c3322308e2b932c4550b0ae9f70daebc39716de3f920831cda96d1640b383", "sha256:3a01be0b583f2bce38b8e9786b75ed33dddc816bba502d8e7a9ca3ca2ead3957",
"sha256:9daddf713cb64d186fa1ae647fea482dc84b643c9284132cd87adb99cd81d638" "sha256:9902ebb4b00481f6fdb0e7db821c007afa45797d81e1d0651735a07de25ece87"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.58.0" "version": "==0.58.1"
}, },
"typing-extensions": { "typing-extensions": {
"hashes": [ "hashes": [

View File

@ -1,5 +1,6 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, ListView from textual.widgets import Header, Footer, ListView
from textual.containers import Container
from renderers.status import StatusListItemRenderer from renderers.status import StatusListItemRenderer
from mastodon.application import MastodonApplication from mastodon.application import MastodonApplication
from mastodon.model.status import Status from mastodon.model.status import Status
@ -12,17 +13,21 @@ class Mastotui(App):
logger.add("mastotui.log", level="DEBUG", rotation="100 MB") logger.add("mastotui.log", level="DEBUG", rotation="100 MB")
logger.remove(0) logger.remove(0)
CSS_PATH="mastotui.tcss"
BINDINGS = [("H", "home", "Home"),("N", "notifications", "Notifications"),("R", "refresh", "Refresh")] BINDINGS = [("H", "home", "Home"),("N", "notifications", "Notifications"),("R", "refresh", "Refresh")]
renderer = StatusListItemRenderer() renderer = StatusListItemRenderer()
mastodon_app = MastodonApplication("mastotui") mastodon_app = MastodonApplication("mastotui")
statuses = [] statuses = []
def compose(self) -> ComposeResult:
yield Header()
yield ListView(id="status_list_view")
yield Footer()
def compose(self) -> ComposeResult:
yield Container(
Header(classes="app_header"),
ListView(id="status_list_view"),
Footer(),
id="dialog"
)
def action_home(self) -> None: def action_home(self) -> None:
self.notify("HOME", timeout=5) self.notify("HOME", timeout=5)
@ -31,19 +36,30 @@ class Mastotui(App):
def action_refresh(self) -> None: def action_refresh(self) -> None:
list_view = self.app.query_one("#status_list_view") list_view = self.app.query_one("#status_list_view")
self.notify("Refresh", timeout=5) if len(self.statuses) == 0:
response = self.mastodon_app.timelines.home_timeline() response = self.mastodon_app.timelines.home()
self.statuses.clear() for status in response:
for status in response: try:
try: logger.trace(status)
logger.trace(status) self.statuses.append(Status.model_validate(status))
self.statuses.append(Status.model_validate(status)) except Exception as ve:
except Exception as ve: logger.debug(status)
logger.debug(status) logger.error(ve)
logger.error(ve) else:
response = self.mastodon_app.timelines.home(since_id=self.statuses[0].status_id)
refresh_list = []
for status in response:
try:
logger.trace(status)
refresh_list.append(Status.model_validate(status))
except Exception as ve:
logger.debug(status)
logger.error(ve)
self.statuses = refresh_list + self.statuses
list_view.clear() list_view.clear()
list_view.extend(self.renderer.render_toots(self.statuses)) list_view.extend(self.renderer.render_toots(self.statuses))
self.notify("Refreshed Home Timeline", timeout=3)
def on_list_view_selected(self, event: ListView.Selected ) -> None: def on_list_view_selected(self, event: ListView.Selected ) -> None:
logger.debug("Select Status Id: {}".format(event.item.status.status_id)) logger.debug("Select Status Id: {}".format(event.item.status.status_id))

212
src/mastotui.tcss Normal file
View File

@ -0,0 +1,212 @@
$polar_night_darkest: #2e3440;
$polar_night_dark: #3b4252;
$polar_night_light: #434c5e;
$polar_night_lightest: #4c566a;
$snow_storm_dark: #d8dee9;
$snow_storm: #e5e9f0;
$snow_storm_light: #eceff4;
$frost_lightest: #8fbcbb;
$frost_light: #88c0d0;
$frost_dark: #81a1c1;
$frost_darkest: #5e81ac;
$aurora_red: #bf616a;
$aurora_orange: #d08770;
$aurora_yellow: #ebcb8b;
$aurora_green: #a3be8c;
$aurora_purple: #b48ead;
StatusScreen {
align: center middle;
}
StatusScreen > Container {
width: 80%;
height: auto;
border: heavy $snow_storm_dark;
}
StatusScreen > Container > StatusFooter {
background: $snow_storm;
height: 1w;
}
.status_footer_key {
background: $snow_storm_dark;
color: $frost_darkest;
padding-left: 1;
padding-right: 1;
}
.status_footer_action {
background: $snow_storm;
color: $frost_darkest;
padding-left: 1;
padding-right: 1;
}
StatusScreen > Container > StatsBar {
background: $polar_night_light;
height: 1w;
}
.status_header_account {
background: $polar_night_light;
color: $frost_light;
}
StatusListItem .stats_bar {
background: $polar_night_light;
height: 1w;
margin-left: 1
}
.stats_bar_replies {
background: $polar_night_light;
color: $aurora_purple;
text-style: bold;
align-horizontal: left;
padding-left: 1;
padding-right: 1;
}
.stats_bar_replies_value {
background: $polar_night_light;
color: $aurora_green;
text-style: bold;
align-horizontal: left;
padding-left: 1;
padding-right: 1;
}
.stats_bar_reblogs {
background: $polar_night_light;
color: $frost_lightest;
color: $aurora_purple;
text-style: bold;
align-horizontal: left;
padding-left: 1;
padding-right: 1;
}
.stats_bar_reblogs_value {
background: $polar_night_light;
color: $frost_lightest;
color: $aurora_green;
text-style: bold;
align-horizontal: left;
padding-left: 1;
padding-right: 1;
}
.stats_bar_favourites {
background: $polar_night_light;
color: $frost_lightest;
color: $aurora_purple;
text-style: bold;
align-horizontal: left;
padding-left: 1;
padding-right: 1;
}
.stats_bar_favourites_value {
background: $polar_night_light;
color: $frost_lightest;
color: $aurora_green;
text-style: bold;
align-horizontal: left;
padding-left: 1;
padding-right: 1;
}
.time_separator {
background: $polar_night_lightest;
margin-left: 1;
width: 100%;
padding: 0;
margin: 0;
margin-left: 1;
text-align: right;
}
.zoom_status_header {
color: $frost_darkest;
background: $polar_night_dark;
text-style: bold;
height: auto;
width: 100%;
}
.zoom_account_header {
background: $polar_night_light;
color: $frost_light;
text-style: bold;
height: auto;
width: 100%;
}
.zoom_status_content {
background: $polar_night_darkest;
width: 100%;
padding: 0;
margin: 0;
}
.status_header {
color: $frost_darkest;
background: $polar_night_dark;
text-style: bold;
height: auto;
width: 100%;
margin-left: 1;
}
.account_header {
background: $polar_night_light;
color: $frost_light;
text-style: bold;
height: auto;
width: 100%;
margin-left: 1;
}
.status_content {
background: $polar_night_darkest;
width: 100%;
padding: 0;
margin: 0;
margin-left: 1;
}
.status_stats {
background: $polar_night_darkest;
height: auto;
width: 100%;
margin-left: 1;
}
.status_replies {
color: $frost_lightest;
align-horizontal: left;
padding-left: 1;
width: auto;
}
.status_boosts {
color: $frost_lightest;
align-horizontal: left;
padding-left: 2;
width: auto;
}
.status_favourites {
color: $frost_lightest;
align-horizontal: left;
padding-left: 2;
width: auto;
}
.status_time {
color: $polar_night_lightest;
align-horizontal: right;
padding-left: 10;
}
Footer {
background: $snow_storm;
}
.footer--description {
background: $snow_storm;
color: $frost_darkest;
}
.footer--key {
background: $snow_storm_dark;
color: $frost_darkest;
}

View File

@ -1,8 +1,13 @@
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.containers import Container from textual.containers import Container, Horizontal
from textual.screen import ModalScreen from textual.screen import ModalScreen
from textual.widgets import Label from textual.widgets import Label, Markdown, Button
from loguru import logger from loguru import logger
from markdownify import markdownify
from PIL import Image
import requests
from widgets.status import StatsBar, StatusFooter
class StatusScreen(ModalScreen): class StatusScreen(ModalScreen):
@ -10,26 +15,106 @@ class StatusScreen(ModalScreen):
super().__init__() super().__init__()
self.status = status self.status = status
BINDINGS = [("q", "back", "Go Back")] CSS_PATH = "../mastotui.tcss"
BINDINGS = [
DEFAULT_CSS = """ ("q", "back", "Close"),
StatusScreen { ("b", "boost", "Boost"),
align: center middle; ("f", "favourite", "Favourite"),
} ("1", "media_1", "1st Media"),
("2", "media_2", "2nd Media"),
StatusScreen > Container { ("3", "media_3", "3rd Media"),
width: auto; ("4", "media_4", "4th Media")
height: auto; ]
}
"""
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
if self.status.reblog is not None:
status_header = "{} ({}) Boosted".format(self.status.account.display_name, self.status.account.acct)
display_name = self.status.reblog.account.display_name
acct = self.status.reblog.account.acct
content = self.status.reblog.content
created_at = self.status.reblog.created_at
replies = self.status.reblog.replies_count
boosts = self.status.reblog.reblogs_count
favourites = self.status.reblog.favourites_count
self.media_attachments = self.status.reblog.media_attachments
else:
status_header = ""
display_name = self.status.account.display_name
acct = self.status.account.acct
content = self.status.content
created_at = self.status.created_at
replies = self.status.replies_count
boosts = self.status.reblogs_count
favourites = self.status.favourites_count
self.media_attachments = self.status.media_attachments
main_bindings = [("q","Close"),
("b", "Boost"),
("f", "Favourite"),
("r", "Reply")]
variable_bindings = []
for index, attachment in enumerate(self.media_attachments):
if index == 0:
variable_bindings.append(("1", "1st Media"))
if index == 1:
variable_bindings.append(("2", "2nd Media"))
if index == 2:
variable_bindings.append(("3", "3rd Media"))
if index == 3:
variable_bindings.append(("4", "4th Media"))
with Container(): with Container():
yield(Label(self.status.status_id)) yield Label(status_header, classes="zoom_status_header")
yield Label("{} ({})".format(display_name, acct), classes="zoom_account_header")
yield Markdown(markdownify(content), classes="zoom_status_content")
yield StatsBar(replies, boosts, favourites)
yield StatusFooter(main_bindings, variable_bindings)
def action_back(self) -> None: def action_back(self) -> None:
logger.debug("Screen Stack {}".format(len(self.app.screen_stack)))
if len(self.app.screen_stack) >= 1: if len(self.app.screen_stack) >= 1:
self.app.pop_screen() self.app.pop_screen()
def action_media_1(self) -> None:
if len(self.media_attachments) > 0:
logger.debug("Opening {} with url: {}".format(self.media_attachments[0].media_type, self.media_attachments[0].url))
if self.media_attachments[0].media_type == "image":
image = Image.open(requests.get(self.media_attachments[0].url, stream=True).raw)
image.show()
def action_media_2(self) -> None:
if len(self.media_attachments) > 1:
logger.debug("Opening {}".format(self.media_attachments[1].url))
if self.media_attachments[1].media_type == "image":
image = Image.open(requests.get(self.media_attachments[1].url, stream=True).raw)
image.show()
def action_media_3(self) -> None:
if len(self.media_attachments) > 2:
logger.debug("Opening {}".format(self.media_attachments[2].url))
if self.media_attachments[2].media_type == "image":
image = Image.open(requests.get(self.media_attachments[2].url, stream=True).raw)
image.show()
def action_media_4(self) -> None:
if len(self.media_attachments) > 3:
logger.debug("Opening {}".format(self.media_attachments[3].url))
if self.media_attachments[3].media_type == "image":
image = Image.open(requests.get(self.media_attachments[3].url, stream=True).raw)
image.show()
def build_footer_value(self, media_attachments):
if len(media_attachments) > 0:
footer_value = "q to go back"
for index, media in enumerate(media_attachments):
footer_value = footer_value + " | [{}] Show Media".format(index+1)
return footer_value
else:
return "q to go back"

View File

@ -1,9 +1,57 @@
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.containers import Horizontal
from textual.widget import Widget
from textual.widgets import ListItem, Label, Markdown from textual.widgets import ListItem, Label, Markdown
from mastodon.model.status import Status from mastodon.model.status import Status
from loguru import logger from loguru import logger
from markdownify import markdownify from markdownify import markdownify
class StatusFooter(Widget):
def __init__(self, main_bindings, variable_bindings):
super().__init__()
self.bindings = main_bindings + variable_bindings
def compose(self) -> ComposeResult:
binding_list = []
for binding in self.bindings:
binding_list.append(Label(binding[0], classes="status_footer_key"))
binding_list.append(Label(binding[1], classes="status_footer_action"))
yield Horizontal(*binding_list, classes="status_footer")
class StatusHeader(Widget):
def __init__(self, account_display_name = None, account_acct = None, boost_display_name = None, boost_acct = None):
super().__init__()
self.account_display_name = account_display_name
self.account_acct = account_acct
self.boost_display_name = boost_display_name
self.boost_acct = boost_acct
def compose(self) -> ComposeResult:
accounts = []
if self.boost_display_name is not None and self.boost_acct is not None:
accounts.append(Label("{} ({}) Boosted -> ".format(self.boost_display_name, self.boost_acct), classes="status_header_boost"))
accounts.append(Label("{} ({})".format(self.account_display_name, self.account_acct), classes="status_header_account"))
yield Horizontal(*accounts, classes="status_header")
class StatsBar(Widget):
def __init__(self, replies, reblogs, favourites):
super().__init__()
self.replies = replies
self.reblogs = reblogs
self.favourites = favourites
def compose(self) -> ComposeResult:
yield Horizontal(
Label("Replies", classes="stats_bar_replies"),
Label("{}".format(self.replies), classes="stats_bar_replies_value"),
Label("Boosts", classes="stats_bar_reblogs"),
Label("{}".format(self.reblogs), classes="stats_bar_reblogs_value"),
Label("Favourited".format(self.favourites), classes="stats_bar_favourites"),
Label("{}".format(self.favourites), classes="stats_bar_favourites_value"),
classes="stats_bar"
)
class StatusListItem(ListItem): class StatusListItem(ListItem):
def __init__(self, status: Status): def __init__(self, status: Status):
super().__init__() super().__init__()
@ -11,16 +59,31 @@ class StatusListItem(ListItem):
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
logger.trace("ID: {} {}".format(self.status.status_id, self.status.content)) logger.trace("ID: {} {}".format(self.status.status_id, self.status.content))
yield Label(self.status.status_id) # yield Label(self.status.status_id)
status_header = "" boost_display_name = None
content = "" boost_acct = None
if self.status.content == "": display_name = None
status_header = "{} ({}) Reblogged".format(self.status.account.display_name, self.status.account.acct) acct = None
if self.status.reblog is not None:
boost_display_name = self.status.account.display_name
boost_acct = self.status.account.acct
display_name = self.status.reblog.account.display_name
acct = self.status.reblog.account.acct
content = self.status.reblog.content content = self.status.reblog.content
yield Label(status_header, id="status_header") created_at = self.status.reblog.created_at
yield Label(self.status.reblog.account.display_name, id="account_header") replies = self.status.reblog.replies_count
boosts = self.status.reblog.reblogs_count
favourites = self.status.reblog.favourites_count
else: else:
yield Label("{} ({})".format(self.status.account.display_name, self.status.account.acct), id="account_header") display_name = self.status.account.display_name
acct = self.status.account.acct
content = self.status.content content = self.status.content
created_at = self.status.created_at
replies = self.status.replies_count
boosts = self.status.reblogs_count
favourites = self.status.favourites_count
yield Markdown(markdownify(content), id="status_content") yield StatusHeader(display_name, acct, boost_display_name, boost_acct)
yield Markdown(markdownify(content), classes="status_content")
yield StatsBar(replies, boosts, favourites)
yield Label("{}".format(created_at), classes="time_separator")