loading inner collections
This commit is contained in:
+134
-14
@@ -1,44 +1,164 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use iced::{Element, Task};
|
||||
use iced::widget::scrollable;
|
||||
use crate::data_provider::import::{load_groups, ImportData};
|
||||
use crate::dictionary::app_data_dir;
|
||||
use crate::import::ImportMessage::*;
|
||||
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||
use crate::styling::*;
|
||||
use iced::widget::{column, row, button, text };
|
||||
use crate::AppState;
|
||||
use crate::import::ImportMessage::*;
|
||||
use iced::widget::scrollable;
|
||||
use iced::widget::{button, column, row, text};
|
||||
use iced::{Element, Task};
|
||||
use iced_core::Alignment::Center;
|
||||
use rfd::AsyncFileDialog;
|
||||
use rusqlite::Connection;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::BufReader;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::task::spawn_blocking;
|
||||
use zip::ZipArchive;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ImportState {
|
||||
state: Arc<Mutex<AppState>>
|
||||
state: Arc<Mutex<AppState>>,
|
||||
path: Option<PathBuf>,
|
||||
import_data: Option<ImportData>,
|
||||
selected_index: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ImportMessage {
|
||||
Back
|
||||
Back,
|
||||
SelectFile,
|
||||
UpdateFile(PathBuf),
|
||||
UpdateImport(ImportData),
|
||||
}
|
||||
|
||||
impl NavigatedPage<ImportMessage> for ImportState {
|
||||
fn navigate(&self, message: &ImportMessage) -> Option<Page> {
|
||||
if let Back = message {
|
||||
return Some(Page::PreviousPage)
|
||||
return Some(Page::PreviousPage);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn navigated(&mut self) {
|
||||
}
|
||||
fn navigated(&mut self) {}
|
||||
|
||||
fn update(&mut self, message: ImportMessage) -> Task<RootMessage> {
|
||||
match message {
|
||||
Back => {}
|
||||
UpdateFile(path) => {
|
||||
self.path = Some(path);
|
||||
return self.load_package();
|
||||
}
|
||||
SelectFile => return Self::select_import_file(),
|
||||
UpdateImport(import) => {
|
||||
self.import_data = Some(import);
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<'_, ImportMessage> {
|
||||
back_overlay(scrollable(column![]).into(), Back)
|
||||
back_overlay(
|
||||
scrollable(
|
||||
column![
|
||||
row![
|
||||
button("Выбрать файл").style(jl_button).on_press(SelectFile),
|
||||
text!("{}", {
|
||||
if let Some(path) = &self.path {
|
||||
path.to_string_lossy().to_string()
|
||||
} else {
|
||||
"Файл не выбран".to_string()
|
||||
}
|
||||
})
|
||||
]
|
||||
.align_y(Center)
|
||||
.spacing(DEFAULT_SPACING)
|
||||
]
|
||||
.spacing(DEFAULT_SPACING),
|
||||
)
|
||||
.into(),
|
||||
Back,
|
||||
)
|
||||
}
|
||||
}
|
||||
impl ImportState {
|
||||
pub fn new(state: Arc<Mutex<AppState>>) -> ImportState {
|
||||
ImportState{
|
||||
state
|
||||
ImportState {
|
||||
state,
|
||||
path: None,
|
||||
import_data: None,
|
||||
selected_index: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn select_import_file() -> Task<RootMessage> {
|
||||
Task::perform(
|
||||
async {
|
||||
let file = AsyncFileDialog::new()
|
||||
.add_filter("Anki", &["apkg"])
|
||||
.pick_file()
|
||||
.await;
|
||||
if let Some(file) = file {
|
||||
return Some(file.path().into());
|
||||
}
|
||||
None
|
||||
},
|
||||
|result| {
|
||||
if let Some(path) = result {
|
||||
RootMessage::Import(UpdateFile(path))
|
||||
} else {
|
||||
RootMessage::None
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_package(&self) -> Task<RootMessage> {
|
||||
let path = self.path.clone().unwrap();
|
||||
Task::perform(
|
||||
async {
|
||||
spawn_blocking(move || {
|
||||
Self::extract_import_file(path)?;
|
||||
let data = Self::read_import_file()?;
|
||||
return Ok(data);
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
},
|
||||
|result: Result<ImportData, ()>| {
|
||||
if let Ok(import) = result {
|
||||
RootMessage::Import(UpdateImport(import))
|
||||
} else {
|
||||
RootMessage::None
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn extract_import_file(path: PathBuf) -> Result<(), ()> {
|
||||
let file = File::open(path).map_err(|_| ())?;
|
||||
let reader = BufReader::new(file);
|
||||
let mut archive = ZipArchive::new(reader).map_err(|_| ())?;
|
||||
let db_file = archive.by_name("collection.anki2");
|
||||
if let Ok(mut file) = db_file {
|
||||
let temp_file_path = app_data_dir().join("import");
|
||||
let mut temp_file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(&temp_file_path)
|
||||
.map_err(|_| ())?;
|
||||
std::io::copy(&mut file, &mut temp_file).map_err(|_| ())?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
fn read_import_file() -> Result<ImportData, ()> {
|
||||
let temp_file_path = app_data_dir().join("import");
|
||||
let connection = Connection::open(&temp_file_path).map_err(|_| ())?;
|
||||
let data = load_groups(&connection);
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user