From 180c9012b1368f2b8197f321cf5f0980b679d503 Mon Sep 17 00:00:00 2001 From: Jazz Turner-Baggs <473256+jazzz@users.noreply.github.com> Date: Mon, 22 Jun 2026 15:46:19 -0700 Subject: [PATCH] Update Cli-Client to use builder --- bin/chat-cli/src/app.rs | 18 ++++++--- bin/chat-cli/src/main.rs | 33 ++++++++++++---- bin/chat-cli/src/ui.rs | 71 +++++++++++++++++++++-------------- core/conversations/src/lib.rs | 2 +- crates/client/src/lib.rs | 4 +- 5 files changed, 84 insertions(+), 44 deletions(-) diff --git a/bin/chat-cli/src/app.rs b/bin/chat-cli/src/app.rs index 239ee7a..534515a 100644 --- a/bin/chat-cli/src/app.rs +++ b/bin/chat-cli/src/app.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use anyhow::Result; use arboard::Clipboard; use crossbeam_channel::Receiver; -use logos_chat::{ChatClient, EphemeralRegistry, Event, RegistrationService, Transport}; +use logos_chat::{ChatClient, ChatStore, Event, IdentityProvider, RegistrationService, Transport}; use serde::{Deserialize, Serialize}; use crate::utils::now; @@ -41,8 +41,14 @@ pub struct AppState { pub active_chat: Option, } -pub struct ChatApp { - pub client: ChatClient, +pub struct ChatApp +where + I: IdentityProvider + Send + 'static, + T: Transport, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ + pub client: ChatClient, events: Receiver, pub state: AppState, /// Ephemeral command output — not persisted, cleared on chat switch. @@ -53,13 +59,15 @@ pub struct ChatApp { state_path: PathBuf, } -impl ChatApp +impl ChatApp where + I: IdentityProvider + Send, T: Transport, R: RegistrationService + Send + 'static, + S: ChatStore + Send, { pub fn new( - client: ChatClient, + client: ChatClient, events: Receiver, user_name: &str, data_dir: &Path, diff --git a/bin/chat-cli/src/main.rs b/bin/chat-cli/src/main.rs index 842faf4..03acd52 100644 --- a/bin/chat-cli/src/main.rs +++ b/bin/chat-cli/src/main.rs @@ -8,7 +8,10 @@ use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; use clap::{Parser, ValueEnum}; use crossbeam_channel::Receiver; -use logos_chat::{ChatClient, Event, HttpRegistry, RegistrationService, StorageConfig, Transport}; +use logos_chat::{ + ChatClient, ChatClientBuilder, ChatStore, Event, HttpRegistry, IdentityProvider, + RegistrationService, StorageConfig, Transport, +}; use app::ChatApp; @@ -113,14 +116,20 @@ fn run(transport: T, cli: &Cli) -> Result<()> { match cli.registry_url.as_deref() { Some(url) => { let registry = HttpRegistry::new(url); - let (client, events) = - ChatClient::open_with_registry(cli.name.clone(), storage, transport, registry) - .map_err(|e| anyhow::anyhow!("{e:?}")) - .context("failed to open chat client with HTTP registry")?; + let (client, events) = ChatClientBuilder::new() + .transport(transport) + // .storage(storage) // Groups Do not support persistence at this time. + .registration(registry) + .build() + .map_err(|e| anyhow::anyhow!("{e:?}")) + .context("failed to open chat client with HTTP registry")?; launch_tui(client, events, cli) } None => { - let (client, events) = ChatClient::open(cli.name.clone(), storage, transport) + let (client, events) = ChatClientBuilder::new() + .transport(transport) + // .storage(storage) // Groups Do not support persistence at this time. + .build() .map_err(|e| anyhow::anyhow!("{e:?}")) .context("failed to open chat client")?; launch_tui(client, events, cli) @@ -128,10 +137,16 @@ fn run(transport: T, cli: &Cli) -> Result<()> { } } -fn launch_tui(client: ChatClient, events: Receiver, cli: &Cli) -> Result<()> +fn launch_tui( + client: ChatClient, + events: Receiver, + cli: &Cli, +) -> Result<()> where + I: IdentityProvider + Send, T: Transport, R: RegistrationService + Send + 'static, + S: ChatStore + Send, { let mut app = ChatApp::new(client, events, &cli.name, &cli.data)?; @@ -209,10 +224,12 @@ fn run_logos_delivery(cli: Cli) -> Result<()> { ) } -fn run_app(terminal: &mut ui::Tui, app: &mut ChatApp) -> Result<()> +fn run_app(terminal: &mut ui::Tui, app: &mut ChatApp) -> Result<()> where + I: IdentityProvider + Send, T: Transport, R: RegistrationService + Send + 'static, + S: ChatStore + Send, { loop { app.process_incoming()?; diff --git a/bin/chat-cli/src/ui.rs b/bin/chat-cli/src/ui.rs index e1b9813..7dd2241 100644 --- a/bin/chat-cli/src/ui.rs +++ b/bin/chat-cli/src/ui.rs @@ -16,7 +16,7 @@ use ratatui::{ widgets::{Block, Borders, List, ListItem, Paragraph, Wrap}, }; -use logos_chat::{RegistrationService, Transport}; +use logos_chat::{ChatStore, IdentityProvider, RegistrationService, Transport}; use crate::app::ChatApp; @@ -38,10 +38,13 @@ pub fn restore() -> io::Result<()> { } /// Draw the UI. -pub fn draw( - frame: &mut Frame, - app: &ChatApp, -) { +pub fn draw(frame: &mut Frame, app: &ChatApp) +where + I: IdentityProvider + Send + 'static, + D: Transport + Send + 'static, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ @@ -58,11 +61,13 @@ pub fn draw( draw_status(frame, app, chunks[3]); } -fn draw_header( - frame: &mut Frame, - app: &ChatApp, - area: Rect, -) { +fn draw_header(frame: &mut Frame, app: &ChatApp, area: Rect) +where + I: IdentityProvider + Send + 'static, + D: Transport + Send + 'static, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ let title = match app.current_session() { Some(session) => { let id = &session.chat_id[..8.min(session.chat_id.len())]; @@ -85,11 +90,13 @@ fn draw_header( frame.render_widget(header, area); } -fn draw_messages( - frame: &mut Frame, - app: &ChatApp, - area: Rect, -) { +fn draw_messages(frame: &mut Frame, app: &ChatApp, area: Rect) +where + I: IdentityProvider + Send + 'static, + D: Transport + Send + 'static, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ let remote_name = app .current_session() .map(|s| s.display_name()) @@ -175,11 +182,13 @@ fn draw_messages( frame.render_stateful_widget(messages_widget, area, &mut list_state); } -fn draw_input( - frame: &mut Frame, - app: &ChatApp, - area: Rect, -) { +fn draw_input(frame: &mut Frame, app: &ChatApp, area: Rect) +where + I: IdentityProvider + Send + 'static, + D: Transport + Send + 'static, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ // Inner width: area minus borders (2). let inner_width = area.width.saturating_sub(2) as usize; let input_len = app.input.len(); @@ -206,11 +215,13 @@ fn draw_input( frame.set_cursor_position((cursor_x, area.y + 1)); } -fn draw_status( - frame: &mut Frame, - app: &ChatApp, - area: Rect, -) { +fn draw_status(frame: &mut Frame, app: &ChatApp, area: Rect) +where + I: IdentityProvider + Send + 'static, + D: Transport + Send + 'static, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ let status = Paragraph::new(app.status.as_str()) .style(Style::default().fg(Color::Gray)) .block(Block::default().title(" Status ").borders(Borders::ALL)) @@ -220,9 +231,13 @@ fn draw_status( } /// Handle keyboard events. -pub fn handle_events( - app: &mut ChatApp, -) -> io::Result { +pub fn handle_events(app: &mut ChatApp) -> io::Result +where + I: IdentityProvider + Send + 'static, + D: Transport + Send + 'static, + R: RegistrationService + Send + 'static, + S: ChatStore + Send + 'static, +{ // Poll for events with a short timeout to allow checking incoming messages if event::poll(std::time::Duration::from_millis(100))? && let Event::Key(key) = event::read()? diff --git a/core/conversations/src/lib.rs b/core/conversations/src/lib.rs index edc093e..f247933 100644 --- a/core/conversations/src/lib.rs +++ b/core/conversations/src/lib.rs @@ -29,6 +29,6 @@ pub use outcomes::{ pub use service_context::ExternalServices; pub use service_traits::{DeliveryService, RegistrationService, WakeupService}; pub use shared_traits::{IdentId, IdentIdRef, IdentityProvider}; -pub use storage::ConversationKind; +pub use storage::{ChatStore, ConversationKind}; pub use types::AddressedEnvelope; pub use utils::{hex_trunc, trunc}; diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 2ba5961..a349036 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -14,8 +14,8 @@ pub use event::Event; // Re-export types callers need to interact with ChatClient. pub use libchat::{ - AddressedEnvelope, ConversationClass, ConversationId, DeliveryService, RegistrationService, - StorageConfig, + AddressedEnvelope, ChatStore, ConversationClass, ConversationId, DeliveryService, + IdentityProvider, RegistrationService, StorageConfig, }; // Re-export bundled registry implementations so callers can pick one without