// This file is part of Deja-Vu. // // Deja-Vu is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Deja-Vu is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Deja-Vu. If not, see . // use core::{action::Action, components::Component, config::Config, state::Mode}; use std::{ iter::zip, sync::{Arc, Mutex}, }; use color_eyre::Result; use crossterm::event::KeyEvent; use ratatui::{ prelude::*, widgets::{Block, Borders, Clear, List, ListItem, Padding, Paragraph}, }; use tokio::sync::mpsc::UnboundedSender; use crate::wim::WimSources; #[derive(Default)] pub struct WimScan { command_tx: Option>, config: Config, mode: Mode, scan_network: bool, wim_sources: Arc>, } impl WimScan { #[must_use] pub fn new(wim_sources: Arc>) -> Self { let wim_sources = wim_sources.clone(); Self { wim_sources, ..Default::default() } } } impl Component for WimScan { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { let _ = key; // to appease clippy Ok(None) } fn register_action_handler(&mut self, tx: UnboundedSender) -> Result<()> { self.command_tx = Some(tx); Ok(()) } fn register_config_handler(&mut self, config: Config) -> Result<()> { self.config = config; Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { Action::FindWimNetwork => self.scan_network = true, Action::SetMode(new_mode) => { self.mode = new_mode; } _ => {} } Ok(None) } fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.mode != Mode::ScanWinSources { return Ok(()); } frame.render_widget(Clear, area); // Prep let [left, right] = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) .areas(area); let [left_title, left_body] = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Length(1), Constraint::Min(1)]) .areas(left); let [right_title, right_body] = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Length(1), Constraint::Min(1)]) .areas(right); // Titles let titles = vec![ Paragraph::new(Line::from("Local").centered()) .block(Block::default().borders(Borders::NONE)), Paragraph::new(Line::from("Network").centered()) .block(Block::default().borders(Borders::NONE)), ]; for (title, area) in zip(titles, [left_title, right_title]) { frame.render_widget(title, area); } // WIM Info if let Ok(wim_sources) = self.wim_sources.lock() { // Local let mut left_list = Vec::new(); if wim_sources.thread_local.is_some() { left_list.push(ListItem::new("Scanning...")); } else { left_list.extend( wim_sources .local .iter() .map(|wimfile| ListItem::new(format!("{}\n\n", wimfile.path))), ); } let left_list = List::new(left_list).block( Block::default() .borders(Borders::ALL) .padding(Padding::new(1, 1, 1, 1)), ); frame.render_widget(left_list, left_body); // Network let mut right_list = Vec::new(); if wim_sources.thread_network.is_some() { right_list.push(ListItem::new("Scanning...")); } else { right_list.extend(wim_sources.network.iter().map(|wimfile| { ListItem::new(format!( "{}\n\n", wimfile.path.split("\\").last().unwrap_or(&wimfile.path) )) })); } let right_list = List::new(right_list).block( Block::default() .borders(Borders::ALL) .padding(Padding::new(1, 1, 1, 1)), ); frame.render_widget(right_list, right_body); } // Done Ok(()) } }