Claude: An other extractor that doesn'T quite work
This commit is contained in:
parent
3d24ac8b57
commit
da3ad2e7b7
@ -3,6 +3,7 @@ use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use crate::installer::validator::*;
|
||||
use crate::installer::downloader::DownloadManager;
|
||||
use crate::installer::SevenZDearchiver;
|
||||
use crate::ui::download_progress::download_progress;
|
||||
use crate::ui::game_selection::game_selection;
|
||||
use crate::ui::installation_progress::installation_progress;
|
||||
@ -182,6 +183,7 @@ impl<> eframe::App for SinfarInstallerApp<> {
|
||||
if self.state == InstallerState::Download {
|
||||
self.start_download();
|
||||
} else if self.state == InstallerState::Installing {
|
||||
//self.start_extract();
|
||||
self.start_installation();
|
||||
}
|
||||
}
|
||||
@ -335,4 +337,40 @@ impl SinfarInstallerApp<> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_extract(&mut self) {
|
||||
|
||||
let dearchiver = crate::installer::SevenZDearchiver::new();
|
||||
let download_state = self.download_state.clone();
|
||||
let error_state = download_state.clone();
|
||||
let eframe_ctx = self.eframe_ctx.clone().expect("eframe context should be set");
|
||||
|
||||
// Placeholder paths for testing
|
||||
let archive_path = std::path::PathBuf::from("C:/Users/Samuel/AppData/Local/Temp/sinfar_installer/sinfar_all_files_v30.7z");
|
||||
let output_dir = std::path::PathBuf::from("C:/Users/Samuel/AppData/Local/Temp/sinfar_installer/test");
|
||||
|
||||
self.runtime.spawn(async move {
|
||||
if let Err(e) = dearchiver.extract(
|
||||
&archive_path,
|
||||
&output_dir,
|
||||
move |progress, eta| {
|
||||
if let Ok(mut state) = download_state.lock() {
|
||||
state.progress = progress;
|
||||
state.estimated_remaining = eta;
|
||||
if state.progress == 1.0 {
|
||||
state.completed = true;
|
||||
}
|
||||
else {
|
||||
state.completed = false;
|
||||
}
|
||||
eframe_ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
).await {
|
||||
if let Ok(mut state) = error_state.lock() {
|
||||
state.error = Some(format!("Extraction failed: {}", e));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
112
rust/src/installer/7z_dearchiver.rs
Normal file
112
rust/src/installer/7z_dearchiver.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{Mutex, watch};
|
||||
use std::io::{Read, Seek};
|
||||
use std::fs;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub struct SevenZDearchiver {
|
||||
cancel_tx: watch::Sender<bool>,
|
||||
cancel_rx: watch::Receiver<bool>,
|
||||
}
|
||||
|
||||
impl SevenZDearchiver {
|
||||
pub fn new() -> Self {
|
||||
let (cancel_tx, cancel_rx) = watch::channel(false);
|
||||
Self {
|
||||
cancel_tx,
|
||||
cancel_rx,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cancel(&self) {
|
||||
let _ = self.cancel_tx.send(true);
|
||||
}
|
||||
|
||||
pub async fn extract<F>(&self, archive_path: &Path, output_dir: &Path, progress_callback: F) -> Result<()>
|
||||
where
|
||||
F: Fn(f32, Duration) + Send + Sync + 'static
|
||||
{
|
||||
// Create wrapper for progress tracking
|
||||
struct ProgressReader<R: Read + Seek> {
|
||||
inner: R,
|
||||
bytes_read: u64,
|
||||
total_size: u64,
|
||||
last_update: Instant,
|
||||
cancel_signal: watch::Receiver<bool>,
|
||||
progress_callback: Arc<Box<dyn Fn(f32, Duration) + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> Read for ProgressReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
// Check cancellation
|
||||
if *self.cancel_signal.borrow() {
|
||||
return Ok(0); // Return 0 to indicate EOF and stop extraction
|
||||
}
|
||||
|
||||
let bytes = self.inner.read(buf)?;
|
||||
self.bytes_read += bytes as u64;
|
||||
|
||||
let now = Instant::now();
|
||||
let elapsed = now.duration_since(self.last_update);
|
||||
|
||||
// Update progress every 100ms
|
||||
if elapsed.as_millis() > 100 {
|
||||
let progress = self.bytes_read as f32 / self.total_size as f32;
|
||||
|
||||
// Calculate estimated time remaining
|
||||
let speed = self.bytes_read as f64 / elapsed.as_secs_f64();
|
||||
let remaining_bytes = self.total_size - self.bytes_read;
|
||||
let eta = if speed > 0.0 {
|
||||
Duration::from_secs_f64(remaining_bytes as f64 / speed)
|
||||
} else {
|
||||
Duration::from_secs(0)
|
||||
};
|
||||
|
||||
(self.progress_callback)(progress, eta);
|
||||
self.last_update = now;
|
||||
}
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> Seek for ProgressReader<R> {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
self.inner.seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
// Start extraction in blocking task
|
||||
let cancel_rx = self.cancel_rx.clone();
|
||||
let progress_cb = Arc::new(Box::new(progress_callback) as Box<dyn Fn(f32, Duration) + Send + Sync>);
|
||||
let archive_path = archive_path.to_owned();
|
||||
let output_dir = output_dir.to_owned();
|
||||
|
||||
tokio::task::spawn_blocking(move || -> Result<()> {
|
||||
let file = fs::File::open(&archive_path)?;
|
||||
let file_size = file.metadata()?.len();
|
||||
|
||||
let progress_reader = ProgressReader {
|
||||
inner: file,
|
||||
bytes_read: 0,
|
||||
total_size: file_size,
|
||||
last_update: Instant::now(),
|
||||
cancel_signal: cancel_rx,
|
||||
progress_callback: progress_cb,
|
||||
};
|
||||
|
||||
sevenz_rust::decompress(progress_reader, &output_dir)?;
|
||||
Ok(())
|
||||
}).await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SevenZDearchiver {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
@ -2,3 +2,6 @@ pub mod downloader;
|
||||
pub mod extractor;
|
||||
pub mod validator;
|
||||
pub mod shortcut;
|
||||
pub mod seven_z_dearchiver;
|
||||
|
||||
pub use seven_z_dearchiver::SevenZDearchiver;
|
112
rust/src/installer/seven_z_dearchiver.rs
Normal file
112
rust/src/installer/seven_z_dearchiver.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{Mutex, watch};
|
||||
use std::io::{Read, Seek};
|
||||
use std::fs;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub struct SevenZDearchiver {
|
||||
cancel_tx: watch::Sender<bool>,
|
||||
cancel_rx: watch::Receiver<bool>,
|
||||
}
|
||||
|
||||
impl SevenZDearchiver {
|
||||
pub fn new() -> Self {
|
||||
let (cancel_tx, cancel_rx) = watch::channel(false);
|
||||
Self {
|
||||
cancel_tx,
|
||||
cancel_rx,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cancel(&self) {
|
||||
let _ = self.cancel_tx.send(true);
|
||||
}
|
||||
|
||||
pub async fn extract<F>(&self, archive_path: &Path, output_dir: &Path, progress_callback: F) -> Result<()>
|
||||
where
|
||||
F: Fn(f32, Duration) + Send + Sync + 'static
|
||||
{
|
||||
// Create wrapper for progress tracking
|
||||
struct ProgressReader<R: Read + Seek> {
|
||||
inner: R,
|
||||
bytes_read: u64,
|
||||
total_size: u64,
|
||||
last_update: Instant,
|
||||
cancel_signal: watch::Receiver<bool>,
|
||||
progress_callback: Arc<Box<dyn Fn(f32, Duration) + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> Read for ProgressReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
// Check cancellation
|
||||
if *self.cancel_signal.borrow() {
|
||||
return Ok(0); // Return 0 to indicate EOF and stop extraction
|
||||
}
|
||||
|
||||
let bytes = self.inner.read(buf)?;
|
||||
self.bytes_read += bytes as u64;
|
||||
|
||||
let now = Instant::now();
|
||||
let elapsed = now.duration_since(self.last_update);
|
||||
|
||||
// Update progress every 100ms
|
||||
if elapsed.as_millis() > 100 {
|
||||
let progress = self.bytes_read as f32 / self.total_size as f32;
|
||||
|
||||
// Calculate estimated time remaining
|
||||
let speed = self.bytes_read as f64 / elapsed.as_secs_f64();
|
||||
let remaining_bytes = self.total_size - self.bytes_read;
|
||||
let eta = if speed > 0.0 {
|
||||
Duration::from_secs_f64(remaining_bytes as f64 / speed)
|
||||
} else {
|
||||
Duration::from_secs(0)
|
||||
};
|
||||
|
||||
(self.progress_callback)(progress, eta);
|
||||
self.last_update = now;
|
||||
}
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> Seek for ProgressReader<R> {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
self.inner.seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
// Start extraction in blocking task
|
||||
let cancel_rx = self.cancel_rx.clone();
|
||||
let progress_cb = Arc::new(Box::new(progress_callback) as Box<dyn Fn(f32, Duration) + Send + Sync>);
|
||||
let archive_path = archive_path.to_owned();
|
||||
let output_dir = output_dir.to_owned();
|
||||
|
||||
tokio::task::spawn_blocking(move || -> Result<()> {
|
||||
let file = fs::File::open(&archive_path)?;
|
||||
let file_size = file.metadata()?.len();
|
||||
|
||||
let progress_reader = ProgressReader {
|
||||
inner: file,
|
||||
bytes_read: 0,
|
||||
total_size: file_size,
|
||||
last_update: Instant::now(),
|
||||
cancel_signal: cancel_rx,
|
||||
progress_callback: progress_cb,
|
||||
};
|
||||
|
||||
sevenz_rust::decompress(progress_reader, &output_dir)?;
|
||||
Ok(())
|
||||
}).await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SevenZDearchiver {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user