Compressing word fields
This commit is contained in:
1 parent
e5622c70de
commit
0de809fcce
4 files changed
+107
-67
No files matched your search
@@ -1,9 +1,9 @@
|
||||
use litemap::LiteMap;
|
||||
use crate::data::entities::WordData;
|
||||
use crate::data::repositories::{DataRepository, DataRepositoryInner};
|
||||
use crate::data::Id;
|
||||
use crate::data_provider::{SqliteDbLayer, TableAccessQuerySet};
|
||||
use litemap::LiteMap;
|
||||
use rusqlite::{Error, Params, Row};
|
||||
use crate::data::{Id, SmallId};
|
||||
|
||||
pub type WordRepository = DataRepository<WordData, WordDataLayer>;
|
||||
pub type WordRepositoryInner = DataRepositoryInner<WordData, WordDataLayer>;
|
||||
@@ -61,7 +61,7 @@ impl TableAccessQuerySet<WordData> for WordQuerySet {
|
||||
}
|
||||
|
||||
fn additional_to_string(map: &LiteMap<Id, String>) -> String {
|
||||
let mut parts = vec![];
|
||||
let mut parts = Vec::with_capacity(map.len() * 2);
|
||||
for (id, value) in map {
|
||||
parts.push(id.to_string());
|
||||
parts.push(value.clone());
|
||||
@@ -69,7 +69,20 @@ fn additional_to_string(map: &LiteMap<Id, String>) -> String {
|
||||
parts.join("")
|
||||
}
|
||||
|
||||
fn additional_from_string_temp(data: String) -> LiteMap<Id, String> {
|
||||
|
||||
let pre_map : LiteMap<String, String> = serde_json::from_str(data.as_str()).unwrap();
|
||||
LiteMap::from(pre_map.iter().map(|(k, v)| (match k.as_str() {
|
||||
"reading" => Id(1),
|
||||
"description" => Id(2),
|
||||
"context" => Id(3),
|
||||
&_ => Id(0) }, v.to_string())).collect())
|
||||
}
|
||||
|
||||
fn additional_from_string(data: String) -> LiteMap<Id, String> {
|
||||
if data.is_empty() {
|
||||
return LiteMap::new()
|
||||
}
|
||||
let parts = data.split('').collect::<Vec<&str>>();
|
||||
let chunks = parts.chunks(2).collect::<Vec<&[&str]>>();
|
||||
let mut map = LiteMap::with_capacity(parts.len());
|
||||
|
||||
+42
-4
@@ -1,16 +1,17 @@
|
||||
use crate::app::AppState;
|
||||
use crate::data::entities::WordData;
|
||||
use crate::data::Id;
|
||||
use crate::data::entities::WordGroup;
|
||||
use crate::data::entities::{CustomField, WordData};
|
||||
use crate::data::repositories::{BatchedRepository, Repository};
|
||||
use crate::data_provider::import::{ImportData, ImportGroup, get_words_of_group, load_groups};
|
||||
use crate::fs::*;
|
||||
use crate::jl_button;
|
||||
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||
use crate::notification::NotificationData::OpenFileError;
|
||||
use crate::notification::{MaybeError, NotificationData};
|
||||
use crate::pages::import::ImportMessage::*;
|
||||
use crate::push_error;
|
||||
use crate::styling::*;
|
||||
use crate::{jl_button, push_error_task};
|
||||
use iced::widget::button::danger;
|
||||
use iced::widget::container::success;
|
||||
use iced::widget::{
|
||||
@@ -25,6 +26,7 @@ use log::info;
|
||||
use parking_lot::Mutex;
|
||||
use rfd::AsyncFileDialog;
|
||||
use rusqlite::Connection;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::BufReader;
|
||||
use std::path::PathBuf;
|
||||
@@ -428,7 +430,19 @@ impl ImportState {
|
||||
let separator = self.separator.clone();
|
||||
let skip_empty = self.skip_empty;
|
||||
let group = self.import_data.as_ref().unwrap().0[self.selected_index].clone();
|
||||
let map_indices = Self::get_mapping_indices(&group);
|
||||
let progress = self.progress.clone().unwrap();
|
||||
if let Err(err) = Self::ensure_fields(&state, &map_indices) {
|
||||
return push_error_task!(err);
|
||||
}
|
||||
let fields: HashMap<String, Id> = HashMap::from_iter(
|
||||
state
|
||||
.custom_fields
|
||||
.read()
|
||||
.iter()
|
||||
.map(|f| (f.identifier.clone(), f.id)),
|
||||
);
|
||||
|
||||
info!("{}", group.name);
|
||||
Task::perform(
|
||||
async move {
|
||||
@@ -439,7 +453,6 @@ impl ImportState {
|
||||
let import_list = get_words_of_group(&connection, group.id)?;
|
||||
let mut words_list = Vec::with_capacity(import_list.len());
|
||||
|
||||
let map_indices = Self::get_mapping_indices(&group);
|
||||
let group_handle;
|
||||
{
|
||||
let group_entity = WordGroup {
|
||||
@@ -474,7 +487,7 @@ impl ImportState {
|
||||
word.tags = collected_string;
|
||||
}
|
||||
&_ => {
|
||||
word.additional.insert((*dest).clone(), collected_string);
|
||||
word.additional.insert(fields[dest], collected_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -554,4 +567,29 @@ impl ImportState {
|
||||
|_| RootMessage::Import(NextProgress),
|
||||
)
|
||||
}
|
||||
|
||||
fn ensure_fields(
|
||||
state: &AppState,
|
||||
import_group: &Vec<(String, Vec<usize>)>,
|
||||
) -> Result<(), NotificationData> {
|
||||
let mut fields_repo = state.custom_fields.write();
|
||||
let mut current_fields: Vec<String> = fields_repo
|
||||
.iter()
|
||||
.map(|field| field.identifier.clone())
|
||||
.collect();
|
||||
current_fields.append(&mut vec!["key".to_string(), "value".to_string(), "tags".to_string()]);
|
||||
for (field, _) in import_group {
|
||||
if current_fields.contains(field) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fields_repo.create_now(CustomField {
|
||||
id: Default::default(),
|
||||
name: field.clone(),
|
||||
identifier: field.clone(),
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -262,19 +262,19 @@ impl RepetitionState {
|
||||
}
|
||||
|
||||
fn draw_reading(&self, word: &WordData) -> Element<'_, RepetitionMessage> {
|
||||
match word.additional.get("reading") {
|
||||
match word.additional.get(&Id(1)) {
|
||||
None => space().into(),
|
||||
Some(reading) => text!("{}", reading).size(24).into(),
|
||||
}
|
||||
}
|
||||
fn draw_context(&self, word: &WordData) -> Element<'_, RepetitionMessage> {
|
||||
match word.additional.get("context") {
|
||||
match word.additional.get(&Id(3)) {
|
||||
None => space().into(),
|
||||
Some(context) => text!("{}", context).size(24).into(),
|
||||
}
|
||||
}
|
||||
fn draw_description(&self, word: &WordData) -> Element<'_, RepetitionMessage> {
|
||||
match word.additional.get("description") {
|
||||
match word.additional.get(&Id(2)) {
|
||||
None => space().into(),
|
||||
Some(context) => text!("{}", context).size(24).into(),
|
||||
}
|
||||
|
||||
+46
-57
@@ -1,5 +1,6 @@
|
||||
use crate::app::AppState;
|
||||
use crate::data::entities::{EntityHandle, WordData};
|
||||
use crate::data::Id;
|
||||
use crate::data::entities::{CustomField, EntityHandle, WordData};
|
||||
use crate::data::repositories::Repository;
|
||||
use crate::pages::word::WordMessage::*;
|
||||
use crate::styling::*;
|
||||
@@ -7,12 +8,14 @@ use iced::widget::button::danger;
|
||||
use iced::widget::space::horizontal;
|
||||
use iced::widget::{button, column, row, rule, scrollable, text, text_input};
|
||||
use iced::{Element, Fill};
|
||||
use iced_core::Padding;
|
||||
|
||||
pub struct WordEditor<Message> {
|
||||
state: AppState,
|
||||
handle: EntityHandle<WordData>,
|
||||
on_delete: Option<Message>,
|
||||
on_edit: Option<Message>,
|
||||
fields: Vec<CustomField>,
|
||||
}
|
||||
|
||||
impl<Message> WordEditor<Message> {
|
||||
@@ -37,7 +40,7 @@ impl<Message> WordEditor<Message> {
|
||||
word.additional.insert(key, "".to_string());
|
||||
}
|
||||
RemoveAdditional(key) => {
|
||||
word.additional.remove(key.as_str());
|
||||
word.additional.remove(&key);
|
||||
}
|
||||
}
|
||||
self.on_edit.take()
|
||||
@@ -45,35 +48,24 @@ impl<Message> WordEditor<Message> {
|
||||
|
||||
pub(crate) fn view(&self) -> Element<'_, WordMessage> {
|
||||
let mut fast_add = row![];
|
||||
let word = self.state.dictionary.read().get_static(self.handle).unwrap();
|
||||
if !word.additional.contains_key("reading") {
|
||||
let word = self
|
||||
.state
|
||||
.dictionary
|
||||
.read()
|
||||
.get_static(self.handle)
|
||||
.unwrap();
|
||||
for field in &self.fields {
|
||||
if !word.additional.contains_key(&field.id) {
|
||||
fast_add = fast_add.push(
|
||||
button("Чтение")
|
||||
button(field.name.as_str())
|
||||
.style(button::text)
|
||||
.on_press(AddAdditional("reading".to_string())),
|
||||
.on_press(AddAdditional(field.id)),
|
||||
);
|
||||
}
|
||||
if !word.additional.contains_key("description") {
|
||||
fast_add = fast_add.push(
|
||||
button("Описание")
|
||||
.style(button::text)
|
||||
.on_press(AddAdditional("description".to_string())),
|
||||
);
|
||||
}
|
||||
|
||||
if !word.additional.contains_key("context") {
|
||||
fast_add = fast_add.push(
|
||||
button("В контексте")
|
||||
.style(button::text)
|
||||
.on_press(AddAdditional("context".to_string())),
|
||||
);
|
||||
}
|
||||
|
||||
let mut col = iced::widget::column![
|
||||
column![
|
||||
text!("Ключ"),
|
||||
text_input("key", &word.key).on_input(SetKey),
|
||||
]
|
||||
column![text!("Ключ"), text_input("key", &word.key).on_input(SetKey),]
|
||||
.spacing(QUARTER_SPACING),
|
||||
column![
|
||||
text!("Значение"),
|
||||
@@ -86,7 +78,10 @@ impl<Message> WordEditor<Message> {
|
||||
]
|
||||
.spacing(QUARTER_SPACING),
|
||||
rule::horizontal(2),
|
||||
scrollable(fast_add),
|
||||
scrollable(fast_add.padding(Padding{
|
||||
|
||||
|
||||
top: 0.0 , right: 0.0 , bottom: 4.0 , left: 0.0 , })).horizontal(),
|
||||
];
|
||||
|
||||
for more in &word.additional {
|
||||
@@ -101,16 +96,26 @@ impl<Message> WordEditor<Message> {
|
||||
]
|
||||
.spacing(DEFAULT_SPACING)
|
||||
]
|
||||
.spacing(DEFAULT_SPACING).into()
|
||||
|
||||
|
||||
|
||||
.spacing(DEFAULT_SPACING)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Message> WordEditor<Message> {
|
||||
pub fn new(handle: EntityHandle<WordData>, state: AppState) -> Self {
|
||||
Self { state, handle, on_delete: None, on_edit: None }
|
||||
let fields = state
|
||||
.custom_fields
|
||||
.read()
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
Self {
|
||||
state,
|
||||
handle,
|
||||
on_delete: None,
|
||||
on_edit: None,
|
||||
fields,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_delete(mut self, message: Message) -> Self {
|
||||
@@ -124,38 +129,22 @@ impl<Message> WordEditor<Message> {
|
||||
}
|
||||
|
||||
impl<Message> WordEditor<Message> {
|
||||
fn get_view_for_more(&self, value: (&String, &String)) -> Element<'_, WordMessage> {
|
||||
match value.0.as_str() {
|
||||
"reading" => self.reading_field(value.1),
|
||||
"description" => self.description_field(value.1),
|
||||
"context" => self.context_field(value.1),
|
||||
_ => self.additional_field(value.1, value.0.clone(), value.0.clone()),
|
||||
fn get_view_for_more(&self, value: (&Id, &String)) -> Element<'_, WordMessage> {
|
||||
let field = self.fields.iter().find(|f| f.id == *value.0).unwrap();
|
||||
match value.0 {
|
||||
_ => self.additional_field(value.1, field.name.as_str(), value.0.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn reading_field(&self, value: &str) -> Element<'_, WordMessage> {
|
||||
self.additional_field(value, "Чтение слова".to_string(), "reading".to_string())
|
||||
}
|
||||
|
||||
fn description_field(&self, value: &str) -> Element<'_, WordMessage> {
|
||||
self.additional_field(value, "Описание".to_string(), "description".to_string())
|
||||
}
|
||||
|
||||
fn context_field(&self, value: &str) -> Element<'_, WordMessage> {
|
||||
self.additional_field(value, "В контексте".to_string(), "context".to_string())
|
||||
}
|
||||
fn additional_field(&self, value: &str, name: String, id: String) -> Element<'_, WordMessage> {
|
||||
fn additional_field(&self, value: &str, name: &str, id: Id) -> Element<'_, WordMessage> {
|
||||
column![
|
||||
text!("{}", name),
|
||||
row![
|
||||
text_input(id.clone().as_str(), value)
|
||||
.on_input({
|
||||
let value = id.clone();
|
||||
move |string| SetAdditional(value.clone(), string)
|
||||
})
|
||||
text_input(name, value)
|
||||
.on_input(move |string| SetAdditional(id, string))
|
||||
.width(Fill),
|
||||
button("-")
|
||||
.on_press(RemoveAdditional(id.clone()))
|
||||
.on_press(RemoveAdditional(id))
|
||||
.style(danger),
|
||||
]
|
||||
.spacing(QUARTER_SPACING),
|
||||
@@ -171,7 +160,7 @@ pub enum WordMessage {
|
||||
SetTags(String),
|
||||
SetKey(String),
|
||||
SetValue(String),
|
||||
AddAdditional(String),
|
||||
RemoveAdditional(String),
|
||||
SetAdditional(String, String),
|
||||
AddAdditional(Id),
|
||||
RemoveAdditional(Id),
|
||||
SetAdditional(Id, String),
|
||||
}
|
||||
Reference in new issue
Block a user