diff --git a/rust-tui/src/bin/integration_test.rs b/rust-tui/src/bin/integration_test.rs index 48483be7e..977b875df 100644 --- a/rust-tui/src/bin/integration_test.rs +++ b/rust-tui/src/bin/integration_test.rs @@ -45,7 +45,7 @@ async fn main() -> Result<()> { ditto.update_transport_config(|config| { config.enable_all_peer_to_peer(); - config.connect.websocket_urls.insert(websocket_url); + config.connect.websocket_urls.insert(websocket_url.clone()); }); // Disable sync with v3 peers and DQL strict mode @@ -60,7 +60,8 @@ async fn main() -> Result<()> { println!("✅ Created Ditto instance and started sync"); // Create todolist instance (loads the app) - let todolist = Todolist::new(ditto)?; + let client_name = env::var("DITTO_CLIENT_NAME").ok(); + let todolist = Todolist::new(ditto, websocket_url, client_name)?; println!("📝 App loaded - Created todolist instance"); // Wait for sync and check for the seeded task diff --git a/rust-tui/src/bin/main.rs b/rust-tui/src/bin/main.rs index 6f8bddc4f..d75659af3 100644 --- a/rust-tui/src/bin/main.rs +++ b/rust-tui/src/bin/main.rs @@ -24,6 +24,14 @@ pub struct Cli { #[clap(long, env = "DITTO_WEBSOCKET_URL")] websocket_url: String, + /// Optional client name to display in the TUI + #[clap(long, env = "DITTO_CLIENT_NAME")] + client_name: Option, + + /// Enable peer-to-peer transports (LAN, Bluetooth). Set to false to force all communication through Big Peer. + #[clap(long, env = "DITTO_P2P_ENABLED", default_value = "true")] + p2p_enabled: bool, + /// Path to write logs on disk #[clap(long, default_value = "/tmp/ditto-quickstart.log")] log: PathBuf, @@ -56,11 +64,18 @@ async fn main() -> Result<()> { cli.app_id, cli.token, cli.custom_auth_url, - cli.websocket_url, + cli.websocket_url.clone(), + cli.p2p_enabled, ) .await?; - let _tui_task = TuiTask::try_spawn(shutdown.clone(), terminal, ditto) - .context("failed to start tui task")?; + let _tui_task = TuiTask::try_spawn( + shutdown.clone(), + terminal, + ditto, + cli.websocket_url, + cli.client_name, + ) + .context("failed to start tui task")?; tracing::info!(success = true, "Initialized!"); // Wait for shutdown trigger @@ -95,6 +110,7 @@ async fn try_init_ditto( token: String, custom_auth_url: String, websocket_url: String, + p2p_enabled: bool, ) -> Result { // We use a temporary directory to store Ditto's local database. // This means that data will not be persistent between runs of the @@ -117,8 +133,16 @@ async fn try_init_ditto( .build()?; ditto.update_transport_config(|config| { - config.enable_all_peer_to_peer(); - //set websocket url + if p2p_enabled { + // Enable all peer-to-peer transports (original behavior) + config.enable_all_peer_to_peer(); + } else { + // Explicitly disable all peer-to-peer transports - only use Big Peer + config.peer_to_peer.bluetooth_le.enabled = false; + config.peer_to_peer.lan.enabled = false; + } + + // Set WebSocket URL for Big Peer connection config.connect.websocket_urls.insert(websocket_url); }); diff --git a/rust-tui/src/tui/mod.rs b/rust-tui/src/tui/mod.rs index f24427ad2..60037326f 100644 --- a/rust-tui/src/tui/mod.rs +++ b/rust-tui/src/tui/mod.rs @@ -26,8 +26,10 @@ impl TuiTask { shutdown: Shutdown, terminal: Terminal>, ditto: Ditto, + websocket_url: String, + client_name: Option, ) -> Result { - let todolist_state = Todolist::new(ditto)?; + let todolist_state = Todolist::new(ditto, websocket_url, client_name)?; let task_context = TuiContext { terminal, shutdown, diff --git a/rust-tui/src/tui/todolist.rs b/rust-tui/src/tui/todolist.rs index aab54e1c3..ae4c4cee8 100644 --- a/rust-tui/src/tui/todolist.rs +++ b/rust-tui/src/tui/todolist.rs @@ -37,6 +37,13 @@ pub struct Todolist { /// Subscriptions cause Ditto to sync selected data from other peers pub tasks_subscription: Arc, + // Connection info for display + /// The WebSocket URL this client is connected to + pub websocket_url: String, + + /// Optional client name for display purposes + pub client_name: Option, + // TUI state below pub mode: TodoMode, @@ -82,7 +89,7 @@ impl TodoItem { } impl Todolist { - pub fn new(ditto: Ditto) -> Result { + pub fn new(ditto: Ditto, websocket_url: String, client_name: Option) -> Result { let (tasks_tx, tasks_rx) = watch::channel(Vec::new()); // Register a subscription, which determines what data syncs to this peer @@ -110,6 +117,8 @@ impl Todolist { tasks_rx, tasks_observer, tasks_subscription, + websocket_url, + client_name, mode: TodoMode::Normal, create_task_title: None, edit_task: None, @@ -155,6 +164,14 @@ impl Todolist { .into_iter() .collect::(); + // Format connection info: "client_name@websocket_url" or just "websocket_url" + let connection_info = if let Some(ref client_name) = self.client_name { + format!(" {}@{} ", client_name, self.websocket_url) + } else { + format!(" {} ", self.websocket_url) + }; + let connection_line = Line::raw(connection_info).cyan(); + let table = Table::new(rows, Constraint::from_percentages([30, 70])) .header(header) .highlight_symbol("❯❯ ") @@ -164,7 +181,10 @@ impl Todolist { .border_type(BorderType::Rounded) .title_top(Line::raw(" Tasks (j↓, k↑, ⏎ toggle done) ").left_aligned()) .title_top(sync_line.right_aligned()) - .title_bottom(" (c: create) (d: delete) (e: edit) (q: quit) "), + .title_bottom( + Line::raw(" (c: create) (d: delete) (e: edit) (q: quit) ").left_aligned(), + ) + .title_bottom(connection_line.right_aligned()), ); StatefulWidget::render(table, area, buf, &mut self.table_state); }