{ "Loading configuration..." }
}; }; // Build YouTube auth card HTML outside the main html! macro let ytauth_html = { let ytauth = ytauth.clone(); let ytauth_loading = ytauth_loading.clone(); let message = message.clone(); let error = error.clone(); if let Some(ref status) = *ytauth { if status.login_session_active { let vnc_url = status.vnc_url.clone().unwrap_or_default(); let on_done = { let ytauth = ytauth.clone(); let ytauth_loading = ytauth_loading.clone(); let message = message.clone(); let error = error.clone(); Callback::from(move |_: MouseEvent| { let ytauth = ytauth.clone(); let ytauth_loading = ytauth_loading.clone(); let message = message.clone(); let error = error.clone(); ytauth_loading.set(true); wasm_bindgen_futures::spawn_local(async move { match api::ytauth_login_stop().await { Ok(_) => { message.set(Some( "YouTube login complete! Cookies exported.".into(), )); if let Ok(s) = api::get_ytauth_status().await { ytauth.set(Some(s)); } } Err(e) => error.set(Some(e.0)), } ytauth_loading.set(false); }); }) }; html! { <>{ "Log into YouTube in the browser below, then click Done." }
if !vnc_url.is_empty() { } > } } else if status.authenticated { let age_text = status .cookie_age_hours .map(|h| format!("cookies {h:.0}h old")) .unwrap_or_else(|| "authenticated".into()); let on_refresh = { let ytauth = ytauth.clone(); let ytauth_loading = ytauth_loading.clone(); let message = message.clone(); let error = error.clone(); Callback::from(move |_: MouseEvent| { let ytauth = ytauth.clone(); let ytauth_loading = ytauth_loading.clone(); let message = message.clone(); let error = error.clone(); ytauth_loading.set(true); wasm_bindgen_futures::spawn_local(async move { match api::ytauth_refresh().await { Ok(_) => { message.set(Some("Cookies refreshed".into())); if let Ok(s) = api::get_ytauth_status().await { ytauth.set(Some(s)); } } Err(e) => error.set(Some(e.0)), } ytauth_loading.set(false); }); }) }; let on_clear = { let ytauth = ytauth.clone(); let message = message.clone(); let error = error.clone(); Callback::from(move |_: MouseEvent| { let ytauth = ytauth.clone(); let message = message.clone(); let error = error.clone(); wasm_bindgen_futures::spawn_local(async move { match api::ytauth_clear_cookies().await { Ok(_) => { message.set(Some("YouTube auth cleared".into())); if let Ok(s) = api::get_ytauth_status().await { ytauth.set(Some(s)); } } Err(e) => error.set(Some(e.0)), } }); }) }; html! { <>{ "Authenticated" } { age_text }
if status.refresh_enabled {{ "Auto-refresh is enabled" }
}{ "Authenticate with YouTube for higher download rate limits (~2000/hr vs ~300/hr) and access to age-restricted content. " } { "This launches a browser where you log into your Google account." }
{ "Warning: " } { "YouTube may permanently suspend accounts that are used with third-party download tools. " } { "Use a throwaway Google account" } { " \u{2014} do not log in with your primary account." }
{ "Loading..." }
} } }; let ytdlp_version_html = if let Some(ref status) = *ytauth { let version = status .ytdlp_version .clone() .unwrap_or_else(|| "not found".into()); if status.ytdlp_update_available { let latest = status.ytdlp_latest.clone().unwrap_or_default(); html! {
{ "yt-dlp update available: " }
{ format!("{version} \u{2192} {latest}") }
{ " \u{2014} run " }
{ "pip install -U yt-dlp" }
{ format!("yt-dlp {version}") } { "\u{2713} up to date" }
} } } else { html! {} }; let lastfm_key_html = { let key_set = ytauth .as_ref() .map(|s| s.lastfm_api_key_set) .unwrap_or(false); if key_set { html! {
{ "\u{2713}" }
{ " API key configured via " }
{ "SHANTY_LASTFM_API_KEY" }
{ "Set " }
{ "SHANTY_LASTFM_API_KEY" }
{ " environment variable. Get a key at " }
{ "last.fm/api/account/create" }
{ " (use any name, leave callback URL blank)." }
{ "\u{2713}" }
{ " API key configured via " }
{ "SHANTY_FANART_API_KEY" }
{ ". Provides artist thumbnails and HD banners." }
{ "Set " }
{ "SHANTY_FANART_API_KEY" }
{ " environment variable. Get a key at " }
{ "fanart.tv" }
{ "." }
{ msg }