from textual import on from textual.app import App, ComposeResult from textual.containers import Horizontal, Vertical from textual.widgets import LoadingIndicator, SelectionList, Select, Label, Header from textual.widgets.selection_list import Selection from tunesynctool import SpotifyDriver, SubsonicDriver, Configuration from tunesynctool.models import Playlist config = Configuration.from_env() class InteractiveApp(App): CSS_PATH = "app.tcss" source = None target = None def __init__(self, **kwargs): super().__init__(**kwargs) self.source = None self.target = None def compose(self) -> ComposeResult: yield Header(name="Spotidrome") yield Vertical( Horizontal( Select( id="source", prompt="Select source", options=[('Subsonic', 'subsonic'), ('Spotify', 'spotify')] ), Select(id="target", prompt="Select target", options=[('Subsonic', 'subsonic'), ('Spotify', 'spotify')]), classes="select-source-target", ), Vertical( SelectionList( id="playlist-list", classes="playlist-list" ), classes="playlist-container", ), classes="main-container" ) @on(Select.Changed) def on_select_changed(self, event: Select.Changed) -> None: if event.control.id == "source": self.source = event.value elif event.control.id == "target": self.target = event.value if self.source and self.target: self.load_playlists() def load_playlists(self): # Load playlists if self.source == 'spotify': driver = SpotifyDriver(config) elif self.source == 'subsonic': driver = SubsonicDriver(config) else: raise ValueError("Invalid source") playlists = driver.get_user_playlists() options = [(playlist.name, playlist.service_id) for playlist in playlists] self.query_one("#playlist-list", expect_type=SelectionList).add_options(options) self.query_one("#playlist-list", expect_type=SelectionList).refresh() @on(SelectionList.SelectedChanged) def on_playlist_selected(self, event: SelectionList.SelectedChanged) -> None: if event.control.id == "playlist-list": selected_playlist = event.control.selected # self.query_one(Label).update(f"Selected playlist: {selected_playlist}")