fix: queuing downloads
This commit is contained in:
@@ -2,14 +2,13 @@ use crate::models::FileDisplayData;
|
|||||||
use ratatui::{layout::Rect, widgets::TableState};
|
use ratatui::{layout::Rect, widgets::TableState};
|
||||||
use soulseek_rs::{types::Download, DownloadStatus};
|
use soulseek_rs::{types::Download, DownloadStatus};
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::{mpsc::Receiver, Arc};
|
use std::sync::{mpsc::Receiver, mpsc::Sender, Arc};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum SearchStatus {
|
pub enum SearchStatus {
|
||||||
Active,
|
Active,
|
||||||
Completed,
|
Completed,
|
||||||
Failed(String),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SearchEntry {
|
pub struct SearchEntry {
|
||||||
@@ -53,6 +52,8 @@ pub struct AppState {
|
|||||||
pub downloads_table_state: TableState,
|
pub downloads_table_state: TableState,
|
||||||
pub downloads_receiver_channel:
|
pub downloads_receiver_channel:
|
||||||
Option<Receiver<(Download, Receiver<DownloadStatus>)>>,
|
Option<Receiver<(Download, Receiver<DownloadStatus>)>>,
|
||||||
|
pub downloads_sender_channel:
|
||||||
|
Option<Sender<(Download, Receiver<DownloadStatus>)>>,
|
||||||
pub active_downloads_count: usize,
|
pub active_downloads_count: usize,
|
||||||
|
|
||||||
// UI State
|
// UI State
|
||||||
@@ -94,6 +95,7 @@ impl AppState {
|
|||||||
downloads: Vec::new(),
|
downloads: Vec::new(),
|
||||||
downloads_table_state,
|
downloads_table_state,
|
||||||
downloads_receiver_channel: None,
|
downloads_receiver_channel: None,
|
||||||
|
downloads_sender_channel: None,
|
||||||
active_downloads_count: 0,
|
active_downloads_count: 0,
|
||||||
|
|
||||||
focused_pane: FocusedPane::Searches,
|
focused_pane: FocusedPane::Searches,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::models::{
|
use crate::models::{
|
||||||
AppState, DownloadEntry, FileDisplayData, FocusedPane,
|
AppState, DownloadEntry, FileDisplayData, FocusedPane, SearchEntry,
|
||||||
SearchEntry, SearchStatus,
|
SearchStatus,
|
||||||
};
|
};
|
||||||
use crate::ui::panes::{
|
use crate::ui::panes::{
|
||||||
render_downloads_pane, render_results_pane, render_searches_pane,
|
render_downloads_pane, render_results_pane, render_searches_pane,
|
||||||
@@ -711,11 +711,6 @@ impl MainTui {
|
|||||||
let selected_search_index = self.state.selected_search_index;
|
let selected_search_index = self.state.selected_search_index;
|
||||||
|
|
||||||
for (idx, search) in self.state.searches.iter_mut().enumerate() {
|
for (idx, search) in self.state.searches.iter_mut().enumerate() {
|
||||||
// Only skip failed searches; allow Active and Completed to update
|
|
||||||
if matches!(search.status, SearchStatus::Failed(_)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poll for new results
|
// Poll for new results
|
||||||
let search_query = search.query.clone();
|
let search_query = search.query.clone();
|
||||||
let search_results = self.client.get_search_results(&search_query);
|
let search_results = self.client.get_search_results(&search_query);
|
||||||
@@ -748,7 +743,9 @@ impl MainTui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mark as completed after timeout (but continue updating)
|
// Mark as completed after timeout (but continue updating)
|
||||||
if search.status == SearchStatus::Active && search.start_time.elapsed() > timeout {
|
if search.status == SearchStatus::Active
|
||||||
|
&& search.start_time.elapsed() > timeout
|
||||||
|
{
|
||||||
search.status = SearchStatus::Completed;
|
search.status = SearchStatus::Completed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,13 +766,15 @@ impl MainTui {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create channel for async download initialization
|
if self.state.downloads_receiver_channel.is_none() {
|
||||||
let (sender, receiver) = mpsc::channel();
|
let (sender, receiver) = mpsc::channel();
|
||||||
self.state.downloads_receiver_channel = Some(receiver);
|
self.state.downloads_receiver_channel = Some(receiver);
|
||||||
|
self.state.downloads_sender_channel = Some(sender);
|
||||||
|
}
|
||||||
|
|
||||||
// Start downloads in background
|
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
let download_dir = self.download_dir.clone();
|
let download_dir = self.download_dir.clone();
|
||||||
|
let sender = self.state.downloads_sender_channel.clone().unwrap();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
for (filename, username, size) in selected_files.into_iter() {
|
for (filename, username, size) in selected_files.into_iter() {
|
||||||
@@ -786,8 +785,14 @@ impl MainTui {
|
|||||||
download_dir.clone(),
|
download_dir.clone(),
|
||||||
) {
|
) {
|
||||||
Ok(rx) => {
|
Ok(rx) => {
|
||||||
// Get the download from client
|
if let Some(download) = client
|
||||||
if let Some(download) = client.get_all_downloads().iter().find(|d| d.filename == filename && d.username == username).cloned() {
|
.get_all_downloads()
|
||||||
|
.iter()
|
||||||
|
.find(|d| {
|
||||||
|
d.filename == filename && d.username == username
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
let _ = sender.send((download, rx));
|
let _ = sender.send((download, rx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::models::{SearchEntry, SearchStatus};
|
use crate::models::{SearchEntry, SearchStatus};
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
border_style, border_type, error_style, header_style, highlight_style,
|
border_style, border_type, header_style, highlight_style, success_style,
|
||||||
success_style, warning_style, HIGHLIGHT_SYMBOL,
|
warning_style, HIGHLIGHT_SYMBOL,
|
||||||
};
|
};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::Rect,
|
layout::Rect,
|
||||||
@@ -33,9 +33,6 @@ pub fn render_searches_pane(
|
|||||||
SearchStatus::Completed => {
|
SearchStatus::Completed => {
|
||||||
Cell::from("Done").style(success_style())
|
Cell::from("Done").style(success_style())
|
||||||
}
|
}
|
||||||
SearchStatus::Failed(msg) => {
|
|
||||||
Cell::from(format!("Failed: {}", msg)).style(error_style())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let results_count = search.results.len();
|
let results_count = search.results.len();
|
||||||
|
|||||||
Reference in New Issue
Block a user