Home Timeline working with image viewing
This commit is contained in:
parent
2be82fb169
commit
661aee6e14
1
Pipfile
1
Pipfile
|
@ -13,6 +13,7 @@ textual = "*"
|
|||
pydantic = "*"
|
||||
pymastodon = {version="*", index="moerks"}
|
||||
markdownify = "*"
|
||||
pillow = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "0ff61328a9369d70ce7094e72d664495cbce99af0e1d0a0f6a81528b966a9ec5"
|
||||
"sha256": "0c92ab9c7331b4c4ef3202f85b81a76f25fc007fb7d6cbf33eb6bc4882e1929d"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -199,6 +199,81 @@
|
|||
"markers": "python_version >= '3.7'",
|
||||
"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": {
|
||||
"hashes": [
|
||||
"sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5",
|
||||
|
@ -302,11 +377,11 @@
|
|||
},
|
||||
"pymastodon": {
|
||||
"hashes": [
|
||||
"sha256:290e12ba161a4c87374ac55a437ee78edf3d0d1dc6d65ab653ceebdd0cba2dfb",
|
||||
"sha256:32526b5da307ad6f64ca5ff028437d23de07e4237e04fc0111ca8522b6f89fd5"
|
||||
"sha256:3c4c054e65368c7c4786fc48d97a64efcced3c6eb95084ee852ccccfc8d04d81",
|
||||
"sha256:7ae4df3e669a749f257a5cd8c6866d9331cf81412f31539dda31e17748493452"
|
||||
],
|
||||
"index": "moerks",
|
||||
"version": "==0.8.0"
|
||||
"version": "==0.16.0"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
|
@ -342,11 +417,11 @@
|
|||
},
|
||||
"textual": {
|
||||
"hashes": [
|
||||
"sha256:5c8c3322308e2b932c4550b0ae9f70daebc39716de3f920831cda96d1640b383",
|
||||
"sha256:9daddf713cb64d186fa1ae647fea482dc84b643c9284132cd87adb99cd81d638"
|
||||
"sha256:3a01be0b583f2bce38b8e9786b75ed33dddc816bba502d8e7a9ca3ca2ead3957",
|
||||
"sha256:9902ebb4b00481f6fdb0e7db821c007afa45797d81e1d0651735a07de25ece87"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.58.0"
|
||||
"version": "==0.58.1"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from textual.app import App, ComposeResult
|
||||
from textual.widgets import Header, Footer, ListView
|
||||
from textual.containers import Container
|
||||
from renderers.status import StatusListItemRenderer
|
||||
from mastodon.application import MastodonApplication
|
||||
from mastodon.model.status import Status
|
||||
|
@ -12,17 +13,21 @@ class Mastotui(App):
|
|||
logger.add("mastotui.log", level="DEBUG", rotation="100 MB")
|
||||
logger.remove(0)
|
||||
|
||||
CSS_PATH="mastotui.tcss"
|
||||
BINDINGS = [("H", "home", "Home"),("N", "notifications", "Notifications"),("R", "refresh", "Refresh")]
|
||||
|
||||
renderer = StatusListItemRenderer()
|
||||
mastodon_app = MastodonApplication("mastotui")
|
||||
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:
|
||||
self.notify("HOME", timeout=5)
|
||||
|
||||
|
@ -31,19 +36,30 @@ class Mastotui(App):
|
|||
|
||||
def action_refresh(self) -> None:
|
||||
list_view = self.app.query_one("#status_list_view")
|
||||
self.notify("Refresh", timeout=5)
|
||||
response = self.mastodon_app.timelines.home_timeline()
|
||||
self.statuses.clear()
|
||||
for status in response:
|
||||
try:
|
||||
logger.trace(status)
|
||||
self.statuses.append(Status.model_validate(status))
|
||||
except Exception as ve:
|
||||
logger.debug(status)
|
||||
logger.error(ve)
|
||||
if len(self.statuses) == 0:
|
||||
response = self.mastodon_app.timelines.home()
|
||||
for status in response:
|
||||
try:
|
||||
logger.trace(status)
|
||||
self.statuses.append(Status.model_validate(status))
|
||||
except Exception as ve:
|
||||
logger.debug(status)
|
||||
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.extend(self.renderer.render_toots(self.statuses))
|
||||
self.notify("Refreshed Home Timeline", timeout=3)
|
||||
|
||||
def on_list_view_selected(self, event: ListView.Selected ) -> None:
|
||||
logger.debug("Select Status Id: {}".format(event.item.status.status_id))
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,8 +1,13 @@
|
|||
from textual.app import ComposeResult
|
||||
from textual.containers import Container
|
||||
from textual.containers import Container, Horizontal
|
||||
from textual.screen import ModalScreen
|
||||
from textual.widgets import Label
|
||||
from textual.widgets import Label, Markdown, Button
|
||||
from loguru import logger
|
||||
from markdownify import markdownify
|
||||
from PIL import Image
|
||||
import requests
|
||||
|
||||
from widgets.status import StatsBar, StatusFooter
|
||||
|
||||
|
||||
class StatusScreen(ModalScreen):
|
||||
|
@ -10,26 +15,106 @@ class StatusScreen(ModalScreen):
|
|||
super().__init__()
|
||||
self.status = status
|
||||
|
||||
BINDINGS = [("q", "back", "Go Back")]
|
||||
|
||||
DEFAULT_CSS = """
|
||||
StatusScreen {
|
||||
align: center middle;
|
||||
}
|
||||
|
||||
StatusScreen > Container {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
"""
|
||||
CSS_PATH = "../mastotui.tcss"
|
||||
BINDINGS = [
|
||||
("q", "back", "Close"),
|
||||
("b", "boost", "Boost"),
|
||||
("f", "favourite", "Favourite"),
|
||||
("1", "media_1", "1st Media"),
|
||||
("2", "media_2", "2nd Media"),
|
||||
("3", "media_3", "3rd Media"),
|
||||
("4", "media_4", "4th Media")
|
||||
]
|
||||
|
||||
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():
|
||||
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:
|
||||
logger.debug("Screen Stack {}".format(len(self.app.screen_stack)))
|
||||
if len(self.app.screen_stack) >= 1:
|
||||
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"
|
||||
|
||||
|
|
|
@ -1,9 +1,57 @@
|
|||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal
|
||||
from textual.widget import Widget
|
||||
from textual.widgets import ListItem, Label, Markdown
|
||||
from mastodon.model.status import Status
|
||||
from loguru import logger
|
||||
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):
|
||||
def __init__(self, status: Status):
|
||||
super().__init__()
|
||||
|
@ -11,16 +59,31 @@ class StatusListItem(ListItem):
|
|||
|
||||
def compose(self) -> ComposeResult:
|
||||
logger.trace("ID: {} {}".format(self.status.status_id, self.status.content))
|
||||
yield Label(self.status.status_id)
|
||||
status_header = ""
|
||||
content = ""
|
||||
if self.status.content == "":
|
||||
status_header = "{} ({}) Reblogged".format(self.status.account.display_name, self.status.account.acct)
|
||||
# yield Label(self.status.status_id)
|
||||
boost_display_name = None
|
||||
boost_acct = None
|
||||
display_name = None
|
||||
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
|
||||
yield Label(status_header, id="status_header")
|
||||
yield Label(self.status.reblog.account.display_name, id="account_header")
|
||||
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
|
||||
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
|
||||
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")
|
||||
|
|
Loading…
Reference in New Issue