diff --git a/src/data_provider/import.rs b/src/data_provider/import.rs index bf59d9b..9c12011 100644 --- a/src/data_provider/import.rs +++ b/src/data_provider/import.rs @@ -5,6 +5,7 @@ use log::info; use rusqlite::Connection; use serde_json::Value; use std::collections::BTreeMap; +use crate::pages::import::AnkiSchema; #[derive(Clone)] pub struct ImportData(pub(crate) Vec); @@ -25,7 +26,18 @@ pub struct ImportNote { pub fields: Vec, } -pub fn load_groups(connection: &Connection) -> Result { +pub fn load_groups(connection: &Connection, schema: AnkiSchema) -> Result { + match schema { + AnkiSchema::Old => { + load_old_schema(connection) + } + AnkiSchema::Beta => { + load_new_schema(connection) + } + } +} + +fn load_old_schema(connection: &Connection) -> Result { let json_models: String = connection .query_one("select models from col", (), |row| row.get(0)) .map_err(|_| IncorrectAnkiFile)?; @@ -82,7 +94,9 @@ pub fn load_groups(connection: &Connection) -> Result Result { + return Err(IncorrectAnkiFile); +} pub fn get_words_of_group( connection: &Connection, group_id: u64, diff --git a/src/pages/import.rs b/src/pages/import.rs index 7284b2c..0de44c1 100644 --- a/src/pages/import.rs +++ b/src/pages/import.rs @@ -6,7 +6,7 @@ use crate::data::repositories::{BatchedRepository, Repository}; use crate::data_provider::import::{ImportData, ImportGroup, get_words_of_group, load_groups}; use crate::fs::*; use crate::navigation::{NavigatedPage, Page, RootMessage}; -use crate::notification::NotificationData::OpenFileError; +use crate::notification::NotificationData::{CompressError, OpenFileError}; use crate::notification::{MaybeError, NotificationData}; use crate::pages::import::ImportMessage::*; use crate::push_error; @@ -33,6 +33,7 @@ use std::path::PathBuf; use std::sync::Arc; use tokio::task::spawn_blocking; use zip::ZipArchive; +use zstd::Decoder; const DEFAULT_FIELDS: [&str; 6] = ["key", "value", "tags", "reading", "context", "description"]; @@ -362,8 +363,8 @@ impl ImportState { Task::perform( async { spawn_blocking(move || { - Self::extract_import_file(path)?; - let data = Self::read_import_file()?; + let schema = Self::extract_import_file(path)?; + let data = Self::read_import_file(schema)?; Ok(data) }) .await @@ -376,7 +377,7 @@ impl ImportState { ) } - fn extract_import_file(path: PathBuf) -> MaybeError { + fn extract_import_file(path: PathBuf) -> Result { let file = File::open(path).map_err(|_| OpenFileError)?; let reader = BufReader::new(file); let mut archive = ZipArchive::new(reader).map_err(|_| OpenFileError)?; @@ -387,20 +388,24 @@ impl ImportState { .truncate(true) .open(&temp_file_path) .map_err(|_| OpenFileError)?; - if let Ok(mut file) = archive.by_name("collection.anki21") { + if let Ok(mut file) = archive.by_name("collection.anki21b") { + let mut decoder = Decoder::new(&mut file).map_err(|_| CompressError)?; + std::io::copy(&mut decoder, &mut temp_file).map_err(|_| OpenFileError)?; + Ok(AnkiSchema::Beta) + } else if let Ok(mut file) = archive.by_name("collection.anki21") { std::io::copy(&mut file, &mut temp_file).map_err(|_| OpenFileError)?; - Ok(()) + Ok(AnkiSchema::Old) } else if let Ok(mut file) = archive.by_name("collection.anki2") { std::io::copy(&mut file, &mut temp_file).map_err(|_| OpenFileError)?; - Ok(()) + Ok(AnkiSchema::Old) } else { Err(OpenFileError) } } - fn read_import_file() -> Result { + fn read_import_file(schema: AnkiSchema) -> Result { let temp_file_path = temp_import_path(); let connection = Connection::open(&temp_file_path).map_err(|_| OpenFileError)?; - let data = load_groups(&connection)?; + let data = load_groups(&connection, schema)?; Ok(data) } fn setup_mapping(&mut self, property_name: String) { @@ -593,3 +598,7 @@ impl ImportState { Ok(()) } } + +pub enum AnkiSchema { + Old, Beta +} \ No newline at end of file