157 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
Search Screen for YouTube TUI
"""
from textual.app import ComposeResult
from textual.containers import Container
from textual.screen import Screen
from textual.widgets import (
Button,
Footer,
Header,
Input,
Static,
)
from youtube_tui.services.youtube import YouTubeService
class SearchScreen(Screen):
"""Screen for searching YouTube videos"""
CSS = """
SearchScreen {
align: center middle;
}
#search-container {
width: 80%;
height: auto;
border: double #555555;
padding: 1 2;
margin: 2 0;
}
#search-input {
width: 100%;
margin: 1 0;
}
#buttons {
width: 100%;
height: auto;
dock: bottom;
}
Button {
width: 20;
margin: 1 1;
}
#status-bar {
dock: bottom;
height: 1;
background: #333333;
color: #aaaaaa;
padding: 0 1;
}
#loading-indicator {
height: 3;
margin: 1 0;
}
"""
BINDINGS = [
("escape", "go_back", "Back"),
("enter", "search", "Search"),
("ctrl+f", "search_from_anywhere", "Search"),
]
def __init__(self):
super().__init__()
self.youtube_service = YouTubeService()
self.search_term = ""
self.is_searching = False
def compose(self) -> ComposeResult:
"""Compose the search screen"""
yield Header()
yield Container(
Static("YouTube Search", id="search-title", classes="title"),
Static("Enter a search term to find YouTube videos", id="search-hint"),
Input(placeholder="Search for videos...", id="search-input"),
Button("Search", id="search-button"),
Button("Cancel", id="cancel-button"),
id="search-container",
)
yield Static(id="status-bar")
yield Footer()
def on_mount(self) -> None:
"""Called when screen is mounted"""
self.query_one(Input).focus()
self.update_status(
"Ready to search - Press Enter to search, Ctrl+F to search from anywhere"
)
def action_search_from_anywhere(self) -> None:
"""Open search from anywhere"""
# This is a fallback for the key binding
self.action_search()
def update_status(self, message: str) -> None:
"""Update the status bar message"""
status_bar = self.query_one("#status-bar", Static)
status_bar.update(f"[bold white]{message}[/bold white]")
def action_search(self) -> None:
"""Perform the search operation"""
input_widget = self.query_one(Input)
search_term = input_widget.value.strip()
if not search_term:
self.update_status("[red]Please enter a search term[/red]")
return
self.search_term = search_term
self.update_status(f"[blue]Searching for: {search_term}[/blue]")
# Trigger search - get the app and push results screen
app = self.app
if hasattr(app, "push_results_screen"):
app.push_results_screen(search_term)
else:
# Fallback if app methods aren't available
from youtube_tui.screens.results import ResultsScreen
self.app.push_screen(ResultsScreen(search_term))
def action_cancel(self) -> None:
"""Handle cancel action"""
self.action_go_back()
def action_go_back(self) -> None:
"""Go back to previous screen"""
self.app.pop_screen()
def action_quit(self) -> None:
"""Quit the application"""
# Only quit if we're at the root level
if len(self.app.screen_stack) <= 2: # Header + Footer + Screen
self.app.exit()
else:
self.action_go_back()
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Handle button presses"""
if event.button.id == "search-button":
self.action_search()
elif event.button.id == "cancel-button":
self.action_quit()
def on_input_submitted(self, event: Input.Submitted) -> None:
"""Handle enter key in search input"""
self.action_search()