21
21
from textual import events , on , work
22
22
from textual .app import App , ComposeResult
23
23
from textual .binding import Binding , BindingType
24
- from textual .containers import Center , Container , Horizontal , ScrollableContainer , Vertical
24
+ from textual .containers import Center , Container , Horizontal , ScrollableContainer , Vertical , Grid
25
25
from textual .reactive import reactive
26
26
from textual .screen import ModalScreen
27
27
from textual .widgets import (
@@ -310,15 +310,21 @@ def compose(self) -> ComposeResult:
310
310
)
311
311
yield Input (id = "input" , placeholder = "Search for a Anime" )
312
312
yield ListView (id = "results" )
313
+
313
314
with TabPane ("Info" , id = "info" , disabled = True ): # Info "ℹ"
314
315
with ScrollableContainer (id = "res_con" ):
315
316
yield Horizontal (
316
317
Image (id = "image" ),
317
318
Markdown (id = "markdown" ),
318
319
id = "res_con_2"
319
320
)
320
-
321
+ yield Select .from_values (
322
+ [], # Leere Liste zu Beginn
323
+ id = "season_filter" ,
324
+ prompt = "Alle Staffeln"
325
+ )
321
326
yield ClickableDataTable (id = "season_list" )
327
+
322
328
with TabPane ("Settings" , id = "setting" ): # Settings "⚙"
323
329
# TODO: dont show unneeded on android
324
330
with ScrollableContainer (id = "settings_container" ):
@@ -389,6 +395,56 @@ async def input_changed(self, event: Input.Changed):
389
395
if event .control .id == "input" :
390
396
self .lookup_anime (event .value )
391
397
398
+ @on (Select .Changed )
399
+ def on_season_filter_changed (self , event : Select .Changed ) -> None :
400
+ if event .control .id == "season_filter" :
401
+ table = self .query_one ("#season_list" , DataTable )
402
+ if not self .current_info :
403
+ return
404
+
405
+ table .clear (columns = True )
406
+ table .add_columns ("FT" , "S" , "F" , "Title" , "Hoster" , "Sprache" )
407
+
408
+ # Liste der gefilterten Episoden speichern
409
+ self .filtered_episodes = []
410
+
411
+ # Temporäre Listen für die Sortierung
412
+ regular_episodes = []
413
+ movie_episodes = []
414
+
415
+ # Episoden in reguläre und Filme aufteilen
416
+ for ep in self .current_info .episodes :
417
+ if event .value == Select .BLANK or str (ep .season ) == event .value :
418
+ if str (ep .season ) == "0" :
419
+ movie_episodes .append (ep )
420
+ else :
421
+ regular_episodes .append (ep )
422
+
423
+ # Zusammenführen der Listen: erst reguläre Episoden, dann Filme
424
+ sorted_episodes = regular_episodes + movie_episodes
425
+ self .filtered_episodes = sorted_episodes
426
+
427
+ # Anzeigen der sortierten Episoden
428
+ c = 0
429
+ for ep in sorted_episodes :
430
+ hl = []
431
+ for h in ep .available_hoster :
432
+ hl .append (hoster .get_key (h ))
433
+
434
+ ll = []
435
+ for l in sort_favorite_lang (ep .available_language , self .language ):
436
+ ll .append (l .name )
437
+
438
+ c += 1
439
+ table .add_row (
440
+ c ,
441
+ "F" if str (ep .season ) == "0" else ep .season ,
442
+ ep .episode_number ,
443
+ escape (ep .title ),
444
+ " " .join (sort_favorite_hoster_by_key (hl , self .hoster )),
445
+ " " .join (ll ),
446
+ )
447
+
392
448
@on (SortableTable .SortChanged )
393
449
async def sortableTable_sortChanged (
394
450
self ,
@@ -637,13 +693,29 @@ async def on_key(self, event: events.Key) -> None:
637
693
async def play_selected (self ):
638
694
dt = self .query_one ("#season_list" , DataTable )
639
695
# TODO: show loading
640
- #dt.set_loading(True)
696
+ # dt.set_loading(True)
641
697
index = self .app .query_one ("#results" , ListView ).index
642
698
series_search_result = self .current [index ]
699
+
700
+ # Verwende filtered_episodes falls vorhanden, sonst current_info.episodes
701
+ if hasattr (self , 'filtered_episodes' ) and self .filtered_episodes :
702
+ episodes_to_use = self .filtered_episodes
703
+ # cursor_row entspricht direkt dem Index in der gefilterten Liste
704
+ selected_index = dt .cursor_row
705
+ else :
706
+ episodes_to_use = self .current_info .episodes
707
+ # Finde die entsprechende Episode basierend auf der Tabellenzeile
708
+ selected_row = dt .get_row_at (dt .cursor_row )
709
+ # Suche die passende Episode anhand der angezeigten Informationen
710
+ selected_index = next ((i for i , ep in enumerate (episodes_to_use )
711
+ if
712
+ (str (ep .season ) if ep .season != 0 else "F" ) == str (selected_row [1 ]) # Prüfe Staffel
713
+ and str (ep .episode_number ) == str (selected_row [2 ])), 0 ) # Prüfe Episodennummer
714
+
643
715
self .play (
644
716
series_search_result = series_search_result ,
645
- episodes = self . current_info . episodes ,
646
- index = dt . cursor_row ,
717
+ episodes = episodes_to_use ,
718
+ index = selected_index ,
647
719
)
648
720
#dt.set_loading(False)
649
721
@@ -665,6 +737,22 @@ async def open_info(self) -> None:
665
737
666
738
series = await self .get_series (series_search_result )
667
739
self .current_info = series
740
+
741
+ season_filter = self .query_one ("#season_filter" , Select )
742
+ unique_seasons = sorted (set (ep .season for ep in series .episodes ))
743
+
744
+ # Sortiere die Staffeln so, dass Filme (Staffel 0) am Ende erscheint
745
+ regular_seasons = [s for s in unique_seasons if s != 0 ]
746
+ movies_season = [s for s in unique_seasons if s == 0 ]
747
+ sorted_seasons = regular_seasons + movies_season
748
+
749
+ season_filter_options = []
750
+ for season in sorted_seasons :
751
+ label = "Filme" if season == 0 else f"Staffel { season } "
752
+ season_filter_options .append ((label , str (season )))
753
+ season_filter .set_options (season_filter_options )
754
+ season_filter .value = Select .BLANK
755
+
668
756
await md .update (series .to_markdown ())
669
757
670
758
if gucken_settings_manager .settings ["settings" ]["image_display" ]:
@@ -677,8 +765,25 @@ async def open_info(self) -> None:
677
765
table .clear (columns = True )
678
766
table .add_columns ("FT" , "S" , "F" , "Title" , "Hoster" , "Sprache" )
679
767
680
- c = 0
768
+ # Sortiere die Episoden entsprechend
769
+
770
+ # Sortiere die Episoden entsprechend der gewünschten Reihenfolge
771
+ sorted_episodes = []
772
+ # Zuerst Specials (S)
681
773
for ep in series .episodes :
774
+ if ep .season == "S" :
775
+ sorted_episodes .append (ep )
776
+ # Dann numerische Staffeln
777
+ for ep in series .episodes :
778
+ if isinstance (ep .season , (int , str )) and ep .season not in ["S" , 0 ]:
779
+ sorted_episodes .append (ep )
780
+ # Zum Schluss Filme (F)
781
+ for ep in series .episodes :
782
+ if ep .season == 0 :
783
+ sorted_episodes .append (ep )
784
+
785
+ c = 0
786
+ for ep in sorted_episodes :
682
787
hl = []
683
788
for h in ep .available_hoster :
684
789
hl .append (hoster .get_key (h ))
@@ -688,9 +793,17 @@ async def open_info(self) -> None:
688
793
ll .append (l .name )
689
794
690
795
c += 1
796
+ # Zeige die Staffeln in der gewünschten Reihenfolge
797
+ if ep .season == "S" :
798
+ season_display = "S"
799
+ elif ep .season == 0 :
800
+ season_display = "F"
801
+ else :
802
+ season_display = ep .season
803
+
691
804
table .add_row (
692
805
c ,
693
- ep . season ,
806
+ season_display ,
694
807
ep .episode_number ,
695
808
escape (ep .title ),
696
809
" " .join (sort_favorite_hoster_by_key (hl , self .hoster )),
0 commit comments