This commit is contained in:
Piotr Dec 2025-04-30 12:26:35 +02:00
parent c0bb7d5aa0
commit 906566825f
No known key found for this signature in database
GPG key ID: D3B5A5D0150D147A
2 changed files with 121 additions and 0 deletions

View file

@ -2,3 +2,5 @@ Flask~=1.1.2
requests~=2.24.0 requests~=2.24.0
python-dotenv~=0.15.0 python-dotenv~=0.15.0
pathvalidate~=2.5.2 pathvalidate~=2.5.2
textual~=3.1.1

119
tui.py Normal file
View file

@ -0,0 +1,119 @@
import sys
from textual import work
from textual.app import App, ComposeResult
from textual.containers import Container
from textual.screen import Screen
from textual.widgets import Header, Button, ListView, ListItem, Footer, Label
from exporter_ng import SlackExporter, SlackConfig
class SlackExporterScreen(Screen):
"""Ekran główny eksportera Slack"""
def __init__(self, exporter: SlackExporter, *args, **kwargs):
super().__init__(*args, **kwargs)
self.exporter = exporter
self.selected_channels = set()
def compose(self) -> ComposeResult:
"""Komponuje widgety na ekranie"""
yield Header(show_clock=True)
yield Container(
ListView(*[
ListItem(Label(ch.short_label, id=ch.id))
for ch in self.exporter.channels
], id="channel-list"),
Button("Eksportuj zaznaczone", variant="primary", id="export-btn"),
id="main-container"
)
yield Footer()
def on_list_view_selected(self, event: ListView.Selected) -> None:
"""Obsługuje zaznaczenie elementu listy"""
item = event.item
item_id = item.children[0].id
if item_id in self.selected_channels:
self.selected_channels.remove(item_id)
item.remove_class("selected")
else:
self.selected_channels.add(item_id)
item.add_class("selected")
@work(exclusive=True)
async def export_channels(self):
"""Eksportuje zaznaczone kanały"""
if not self.selected_channels:
self.notify("Nie wybrano żadnych kanałów")
return
# self.notify("Rozpoczynam eksport...")
# self.exporter.export_channels(list(self.selected_channels))
# # for channel_id in self.selected_channels:
# # self.notify(f"Eksportuję kanał {channel_id}...")
# # self.exporter.export_channel_history(channel_id)
# self.notify("Eksport zakończony")
self.app.exit(return_code=8080)
async def on_button_pressed(self, event: Button.Pressed) -> None:
"""Obsługuje kliknięcie przycisku"""
if event.button.id == "export-btn":
self.export_channels()
class SlackTUI(App):
"""Główna klasa interfejsu użytkownika"""
CSS = """
#main-container {
layout: vertical;
height: 100%;
padding: 1;
}
ListView {
height: 1fr;
border: solid green;
}
.selected {
background: $accent;
color: $text;
}
Button {
margin: 1;
width: 100%;
}
"""
def __init__(self, exporter: SlackExporter):
super().__init__()
self.exporter = exporter
self._screen = SlackExporterScreen(self.exporter)
def on_mount(self) -> None:
"""Wywoływane przy montowaniu aplikacji"""
self.push_screen(self._screen)
def get_selection(self):
return self._screen.selected_channels
def get_return_code(self):
return self._return_code
def run_tui(exporter: SlackExporter):
"""Uruchamia interfejs użytkownika"""
app = SlackTUI(exporter)
app.run()
if app.get_return_code() == 8080:
exporter.export_channels(app.get_selection())
if __name__ == "__main__":
try:
config = SlackConfig.from_env()
exporter = SlackExporter(config)
run_tui(exporter)
except Exception as e:
print(f"Błąd: {e}")
sys.exit(1)