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 std::sync::Arc;
|
||||||
use crate::installer::validator::*;
|
use crate::installer::validator::*;
|
||||||
use crate::installer::downloader::DownloadManager;
|
use crate::installer::downloader::DownloadManager;
|
||||||
|
use crate::installer::SevenZDearchiver;
|
||||||
use crate::ui::download_progress::download_progress;
|
use crate::ui::download_progress::download_progress;
|
||||||
use crate::ui::game_selection::game_selection;
|
use crate::ui::game_selection::game_selection;
|
||||||
use crate::ui::installation_progress::installation_progress;
|
use crate::ui::installation_progress::installation_progress;
|
||||||
@ -182,6 +183,7 @@ impl<> eframe::App for SinfarInstallerApp<> {
|
|||||||
if self.state == InstallerState::Download {
|
if self.state == InstallerState::Download {
|
||||||
self.start_download();
|
self.start_download();
|
||||||
} else if self.state == InstallerState::Installing {
|
} else if self.state == InstallerState::Installing {
|
||||||
|
//self.start_extract();
|
||||||
self.start_installation();
|
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 extractor;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
pub mod shortcut;
|
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