From 496d3786e73b587f4c367668057b4a0bd77a46af Mon Sep 17 00:00:00 2001 From: continuist Date: Mon, 16 Jun 2025 20:05:37 -0400 Subject: [PATCH] Delete unneeded source file --- backend/crates/sharenet-tui-memory/src/tui.rs | 464 ------------------ 1 file changed, 464 deletions(-) delete mode 100644 backend/crates/sharenet-tui-memory/src/tui.rs diff --git a/backend/crates/sharenet-tui-memory/src/tui.rs b/backend/crates/sharenet-tui-memory/src/tui.rs deleted file mode 100644 index 03c2803..0000000 --- a/backend/crates/sharenet-tui-memory/src/tui.rs +++ /dev/null @@ -1,464 +0,0 @@ -use std::io; -use std::sync::mpsc; -use std::thread; -use std::time::Duration; -use std::collections::VecDeque; - -use application::UseCase; -use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, -}; -use domain::{CreateProduct, CreateUser, Product, User}; -use ratatui::{ - backend::{Backend, CrosstermBackend}, - layout::{Constraint, Direction, Layout}, - style::{Color, Style}, - widgets::{Block, Borders, List, ListItem, Paragraph, Wrap}, - Frame, Terminal, -}; -use textwrap; - -const MAX_HISTORY: usize = 100; - -pub struct App { - input: String, - messages: Vec, - should_quit: bool, - command_history: VecDeque, - history_index: Option, - cursor_position: usize, -} - -impl App { - pub fn new() -> Self { - Self { - input: String::new(), - messages: vec!["Welcome to Sharenet CLI!".to_string()], - should_quit: false, - command_history: VecDeque::with_capacity(MAX_HISTORY), - history_index: None, - cursor_position: 0, - } - } - - pub fn add_message(&mut self, message: String) { - self.messages.push(message); - } - - pub fn clear_input(&mut self) { - self.input.clear(); - self.cursor_position = 0; - } - - pub fn add_to_history(&mut self, command: String) { - if !command.trim().is_empty() { - self.command_history.push_front(command); - if self.command_history.len() > MAX_HISTORY { - self.command_history.pop_back(); - } - } - } - - pub fn move_cursor(&mut self, delta: isize) { - let new_pos = self.cursor_position as isize + delta; - if new_pos >= 0 && new_pos <= self.input.len() as isize { - self.cursor_position = new_pos as usize; - } - } - - pub fn insert_char(&mut self, c: char) { - self.input.insert(self.cursor_position, c); - self.cursor_position += 1; - } - - pub fn delete_char(&mut self) { - if self.cursor_position > 0 { - self.input.remove(self.cursor_position - 1); - self.cursor_position -= 1; - } - } -} - -pub async fn run_tui(user_service: U, product_service: P) -> anyhow::Result<()> -where - U: UseCase + Clone + Send + 'static, - P: UseCase + Clone + Send + 'static, -{ - // Setup terminal - enable_raw_mode()?; - let mut stdout = io::stdout(); - execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; - let backend = CrosstermBackend::new(stdout); - let mut terminal = Terminal::new(backend)?; - - // Create app and run it - let app = App::new(); - let res = run_app(&mut terminal, app, user_service, product_service).await; - - // Restore terminal - disable_raw_mode()?; - execute!( - terminal.backend_mut(), - LeaveAlternateScreen, - DisableMouseCapture - )?; - terminal.show_cursor()?; - - if let Err(err) = res { - println!("{:?}", err); - } - - Ok(()) -} - -async fn run_app( - terminal: &mut Terminal, - mut app: App, - user_service: U, - product_service: P, -) -> anyhow::Result<()> -where - U: UseCase + Clone + Send + 'static, - P: UseCase + Clone + Send + 'static, -{ - let (tx, rx) = mpsc::channel(); - let user_service_clone = user_service.clone(); - let product_service_clone = product_service.clone(); - - // Spawn a thread to handle user input - thread::spawn(move || { - loop { - if event::poll(Duration::from_millis(50)).unwrap() { - if let Event::Key(key) = event::read().unwrap() { - tx.send(key).unwrap(); - } - } - } - }); - - loop { - terminal.draw(|f| ui(f, &app))?; - - if let Ok(key) = rx.try_recv() { - match key.code { - KeyCode::Char(c) => { - app.insert_char(c); - } - KeyCode::Backspace => { - app.delete_char(); - } - KeyCode::Left => { - app.move_cursor(-1); - } - KeyCode::Right => { - app.move_cursor(1); - } - KeyCode::Up => { - if let Some(index) = app.history_index { - if index + 1 < app.command_history.len() { - app.history_index = Some(index + 1); - app.input = app.command_history[index + 1].clone(); - app.cursor_position = app.input.len(); - } - } else if !app.command_history.is_empty() { - app.history_index = Some(0); - app.input = app.command_history[0].clone(); - app.cursor_position = app.input.len(); - } - } - KeyCode::Down => { - if let Some(index) = app.history_index { - if index > 0 { - app.history_index = Some(index - 1); - app.input = app.command_history[index - 1].clone(); - app.cursor_position = app.input.len(); - } else { - app.history_index = None; - app.clear_input(); - } - } - } - KeyCode::Enter => { - let input = app.input.clone(); - app.add_to_history(input.clone()); - app.clear_input(); - app.history_index = None; - - // Display the command in a distinct color - app.add_message(format!("> {}", input)); - - // Handle commands - match input.trim() { - "exit" => { - app.add_message("Goodbye!".to_string()); - app.should_quit = true; - } - "help" => { - print_help(&mut app); - } - cmd if cmd.starts_with("user create") => { - match parse_user_create(cmd) { - Ok((username, email)) => { - match user_service_clone - .create(CreateUser { username, email }) - .await - { - Ok(user) => app.add_message(format!("Created user: {:?}", user)), - Err(e) => app.add_message(format!("Error: {}", e)), - } - } - Err(e) => app.add_message(format!("Error: {}", e)), - } - } - "user list" => { - match user_service_clone.list().await { - Ok(users) => app.add_message(format!("Users: {:?}", users)), - Err(e) => app.add_message(format!("Error: {}", e)), - } - } - cmd if cmd.starts_with("product create") => { - match parse_product_create(cmd) { - Ok((name, description)) => { - match product_service_clone - .create(CreateProduct { name, description }) - .await - { - Ok(product) => app.add_message(format!("Created product: {:?}", product)), - Err(e) => app.add_message(format!("Error: {}", e)), - } - } - Err(e) => app.add_message(format!("Error: {}", e)), - } - } - "product list" => { - match product_service_clone.list().await { - Ok(products) => app.add_message(format!("Products: {:?}", products)), - Err(e) => app.add_message(format!("Error: {}", e)), - } - } - "" => {} - _ => { - app.add_message("Unknown command. Type 'help' for available commands.".to_string()); - } - } - } - KeyCode::Esc => { - app.should_quit = true; - } - _ => {} - } - } - - if app.should_quit { - return Ok(()); - } - } -} - -fn print_help(app: &mut App) { - app.add_message("\nAvailable commands:".to_string()); - app.add_message(" user create -u -e ".to_string()); - app.add_message(" Example: user create -u \"john doe\" -e \"john@example.com\"".to_string()); - app.add_message(" user list".to_string()); - app.add_message(" product create -n -d ".to_string()); - app.add_message(" Example: product create -n \"My Product\" -d \"A great product description\"".to_string()); - app.add_message(" product list".to_string()); - app.add_message("\nTips:".to_string()); - app.add_message(" - Use quotes for values with spaces".to_string()); - app.add_message(" - Use Up/Down arrows to navigate command history".to_string()); - app.add_message(" - Press Esc to exit".to_string()); - app.add_message(" - Type 'help' to show this message".to_string()); -} - -fn ui(f: &mut Frame, app: &App) { - // Create the layout - let chunks = Layout::default() - .direction(Direction::Vertical) - .margin(1) - .constraints([ - Constraint::Min(1), - Constraint::Length(3), - ]) - .split(f.size()); - - // Create the messages list with styling and wrapping - let messages: Vec = app - .messages - .iter() - .flat_map(|msg| { - let style = if msg.starts_with("Error:") { - Style::default().fg(Color::Red) - } else if msg.starts_with("Created") { - Style::default().fg(Color::Green) - } else if msg.starts_with(">") { - Style::default().fg(Color::Cyan) - } else { - Style::default() - }; - - // Calculate available width for text (accounting for borders and margins) - let available_width = chunks[0].width.saturating_sub(2) as usize; - - // Split message into wrapped lines - let wrapped_lines = textwrap::wrap(msg, available_width); - - // Convert each wrapped line into a ListItem - wrapped_lines.into_iter().map(move |line| { - ListItem::new(line.to_string()).style(style) - }) - }) - .collect(); - - let messages = List::new(messages) - .block(Block::default().title("Messages").borders(Borders::ALL)); - f.render_widget(messages, chunks[0]); - - // Create the input box with cursor and wrapping - let input = Paragraph::new(app.input.as_str()) - .style(Style::default().fg(Color::Yellow)) - .block(Block::default().title("Input (Press 'Esc' to exit)").borders(Borders::ALL)) - .wrap(Wrap { trim: true }); - f.render_widget(input, chunks[1]); - - // Show cursor - f.set_cursor( - chunks[1].x + app.cursor_position as u16 + 1, - chunks[1].y + 1, - ); -} - -fn parse_user_create(cmd: &str) -> anyhow::Result<(String, String)> { - let parts: Vec<&str> = cmd.split_whitespace().collect(); - if parts.len() < 6 { - return Err(anyhow::anyhow!( - "Invalid command format. Use: user create -u -e \nExample: user create -u \"john doe\" -e \"john@example.com\"" - )); - } - - let mut username = None; - let mut email = None; - let mut current_arg = None; - let mut current_value = Vec::new(); - - // Skip "user create" command - let mut i = 2; - while i < parts.len() { - match parts[i] { - "-u" => { - if let Some(arg_type) = current_arg { - match arg_type { - "username" => username = Some(current_value.join(" ")), - "email" => email = Some(current_value.join(" ")), - _ => {} - } - } - current_arg = Some("username"); - current_value.clear(); - i += 1; - } - "-e" => { - if let Some(arg_type) = current_arg { - match arg_type { - "username" => username = Some(current_value.join(" ")), - "email" => email = Some(current_value.join(" ")), - _ => {} - } - } - current_arg = Some("email"); - current_value.clear(); - i += 1; - } - _ => { - if current_arg.is_some() { - current_value.push(parts[i].trim_matches('"')); - } - i += 1; - } - } - } - - // Handle the last argument - if let Some(arg_type) = current_arg { - match arg_type { - "username" => username = Some(current_value.join(" ")), - "email" => email = Some(current_value.join(" ")), - _ => {} - } - } - - match (username, email) { - (Some(u), Some(e)) if !u.is_empty() && !e.is_empty() => Ok((u, e)), - _ => Err(anyhow::anyhow!( - "Invalid command format. Use: user create -u -e \nExample: user create -u \"john doe\" -e \"john@example.com\"" - )), - } -} - -fn parse_product_create(cmd: &str) -> anyhow::Result<(String, String)> { - let parts: Vec<&str> = cmd.split_whitespace().collect(); - if parts.len() < 6 { - return Err(anyhow::anyhow!( - "Invalid command format. Use: product create -n -d \nExample: product create -n \"My Product\" -d \"A great product description\"" - )); - } - - let mut name = None; - let mut description = None; - let mut current_arg = None; - let mut current_value = Vec::new(); - - // Skip "product create" command - let mut i = 2; - while i < parts.len() { - match parts[i] { - "-n" => { - if let Some(arg_type) = current_arg { - match arg_type { - "name" => name = Some(current_value.join(" ")), - "description" => description = Some(current_value.join(" ")), - _ => {} - } - } - current_arg = Some("name"); - current_value.clear(); - i += 1; - } - "-d" => { - if let Some(arg_type) = current_arg { - match arg_type { - "name" => name = Some(current_value.join(" ")), - "description" => description = Some(current_value.join(" ")), - _ => {} - } - } - current_arg = Some("description"); - current_value.clear(); - i += 1; - } - _ => { - if current_arg.is_some() { - current_value.push(parts[i].trim_matches('"')); - } - i += 1; - } - } - } - - // Handle the last argument - if let Some(arg_type) = current_arg { - match arg_type { - "name" => name = Some(current_value.join(" ")), - "description" => description = Some(current_value.join(" ")), - _ => {} - } - } - - match (name, description) { - (Some(n), Some(d)) if !n.is_empty() && !d.is_empty() => Ok((n, d)), - _ => Err(anyhow::anyhow!( - "Invalid command format. Use: product create -n -d \nExample: product create -n \"My Product\" -d \"A great product description\"" - )), - } -} \ No newline at end of file