add SPA config UI, wire media/rss adapters, event-driven layout push
- React SPA: dashboard, data sources CRUD, widgets CRUD, layout builder, presets. TanStack Router + Query, shadcn/ui, Vite proxy to :3000 - wire media + rss adapters into polling loop, remove xtb source type - media adapter: read username/password from headers, proper subsonic auth - event handler: subscribe to LayoutChanged, push screen update to clients - fix clippy warnings across workspace (Default impls, collapsible ifs, redundant closures, is_none_or, unused imports)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
use domain::{DataSource, DataSourceConfig, DataSourcePort, DataSourceType, Value};
|
||||
use media_adapter::MediaAdapter;
|
||||
use std::time::Duration;
|
||||
|
||||
fn subsonic_response(playing: bool) -> serde_json::Value {
|
||||
if playing {
|
||||
@@ -28,10 +28,10 @@ fn subsonic_response(playing: bool) -> serde_json::Value {
|
||||
}
|
||||
|
||||
async fn start_fake_subsonic(playing: bool) -> String {
|
||||
let app = axum::Router::new()
|
||||
.route("/rest/getNowPlaying.view", axum::routing::get(move || async move {
|
||||
axum::response::Json(subsonic_response(playing))
|
||||
}));
|
||||
let app = axum::Router::new().route(
|
||||
"/rest/getNowPlaying.view",
|
||||
axum::routing::get(move || async move { axum::response::Json(subsonic_response(playing)) }),
|
||||
);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
@@ -47,8 +47,11 @@ fn make_source(url: String) -> DataSource {
|
||||
poll_interval: Duration::from_secs(5),
|
||||
config: DataSourceConfig {
|
||||
url: Some(url),
|
||||
headers: vec![],
|
||||
api_key: Some("testtoken".into()),
|
||||
headers: vec![
|
||||
("username".into(), "test".into()),
|
||||
("password".into(), "testpass".into()),
|
||||
],
|
||||
api_key: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -62,8 +65,14 @@ async fn returns_now_playing_info() {
|
||||
let result = adapter.poll(&source).await.unwrap();
|
||||
|
||||
assert_eq!(result.get_path("$.playing"), Some(&Value::Bool(true)));
|
||||
assert_eq!(result.get_path("$.title"), Some(&Value::String("Believer".into())));
|
||||
assert_eq!(result.get_path("$.artist"), Some(&Value::String("Imagine Dragons".into())));
|
||||
assert_eq!(
|
||||
result.get_path("$.title"),
|
||||
Some(&Value::String("Believer".into()))
|
||||
);
|
||||
assert_eq!(
|
||||
result.get_path("$.artist"),
|
||||
Some(&Value::String("Imagine Dragons".into()))
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user