import streamlit as st import httpx import time from pathlib import Path from utils import get_logger, get_host_ip, API_PORT logger = get_logger(__name__) # Config - Use host IP so the browser can find the API HOST_IP = get_host_ip() API_URL = f"http://{HOST_IP}:{API_PORT}" st.set_page_config( page_title="Boys Streaming 📺", page_icon="📺", layout="wide" ) # Custom CSS for big buttons and clean look st.markdown(""" """, unsafe_allow_html=True) # Session State Initialization if 'selected_stories' not in st.session_state: st.session_state.selected_stories = [] if 'library' not in st.session_state: st.session_state.library = None def fetch_library(): try: response = httpx.get(f"{API_URL}/library") if response.status_code == 200: st.session_state.library = response.json() else: st.error("Failed to fetch library from API.") except Exception as e: st.error(f"Could not connect to API: {e}") def toggle_story(story_path): if story_path in st.session_state.selected_stories: st.session_state.selected_stories.remove(story_path) else: if len(st.session_state.selected_stories) < 3: st.session_state.selected_stories.append(story_path) else: st.warning("Only 3 stories allowed!") def start_bedtime(): if len(st.session_state.selected_stories) != 3: st.error("Please pick exactly 3 stories first!") return # Auto-pick one music track if not st.session_state.library['music']: st.error("No music tracks found in library (> 2h)!") return import random music_track = random.choice(st.session_state.library['music']) playlist = st.session_state.selected_stories + [music_track['path']] try: response = httpx.post(f"{API_URL}/cast", json={"video_paths": playlist}) if response.status_code == 200: st.success("Bedtime ritual started! Casting to Chromecast...") else: st.error("Failed to start casting.") except Exception as e: st.error(f"Error starting bedtime: {e}") # --- UI Layout --- st.title("📺 Boys Streaming - Bedtime!") if st.button("🔄 Refresh Library"): fetch_library() if not st.session_state.library: fetch_library() if st.session_state.library: stories = st.session_state.library.get('stories', []) st.subheader(f"📖 Pick 3 Stories ({len(st.session_state.selected_stories)}/3)") # Display stories in a grid cols_per_row = 4 for i in range(0, len(stories), cols_per_row): cols = st.columns(cols_per_row) for j, col in enumerate(cols): if i + j < len(stories): story = stories[i + j] is_selected = story['path'] in st.session_state.selected_stories with col: # Use a unique key for each button thumb_url = f"{API_URL}/thumbs/{story['thumbnail']}" st.image(thumb_url, use_container_width=True) label = f"✅ {story['filename']}" if is_selected else story['filename'] if st.button(label, key=f"btn_{story['id']}"): toggle_story(story['path']) st.rerun() st.divider() # Action area col1, col2 = st.columns(2) with col1: if st.button("🚀 START BEDTIME", type="primary", use_container_width=True): start_bedtime() with col2: if st.button("🛑 STOP CASTING", use_container_width=True): httpx.post(f"{API_URL}/stop") st.warning("Casting stopped.") # Status Monitor st.divider() status_placeholder = st.empty() # Auto-refresh status try: status_resp = httpx.get(f"{API_URL}/status") if status_resp.status_code == 200: status = status_resp.json() if status.get('is_playing'): status_placeholder.info(f"Currently Playing item index: {status.get('current_index', 0) + 1} of {status.get('queue_len', 0)}") else: status_placeholder.text("Chromecast is idle.") except: pass else: st.info("Waiting for library scan...") time.sleep(2) st.rerun()