Fix display and sync bugs

This commit is contained in:
micialware committed 2026-10-03 21:27:13 +03:00
1 parent 5b2b48c88f
commit 0b23da9eda
4 files changed
+46 -17

No files matched your search

+14
View File
@@ -24,6 +24,8 @@ fn create_tables(conn: &Connection) {
make_card_stats(conn).expect("Failed to init table"); make_card_stats(conn).expect("Failed to init table");
make_history(conn).expect("Failed to init table"); make_history(conn).expect("Failed to init table");
make_custom_fields(conn).expect("Failed to init table"); make_custom_fields(conn).expect("Failed to init table");
make_exams(conn).expect("Failed to init table");
make_exam_entry(conn).expect("Failed to init table");
} }
fn make_settings(conn: &Connection) -> Result<(), rusqlite::Error> { fn make_settings(conn: &Connection) -> Result<(), rusqlite::Error> {
@@ -68,6 +70,18 @@ fn make_custom_fields(conn: &Connection) -> Result<(), rusqlite::Error> {
Ok(()) Ok(())
} }
fn make_exams(conn: &Connection) -> Result<(), rusqlite::Error> {
let query = include_str!("../../sql/exam.sql");
conn.execute(query, ())?;
Ok(())
}
fn make_exam_entry(conn: &Connection) -> Result<(), rusqlite::Error> {
let query = include_str!("../../sql/exam_entry.sql");
conn.execute(query, ())?;
Ok(())
}
pub fn default_connection() -> Connection { pub fn default_connection() -> Connection {
let db_file = db_path(); let db_file = db_path();
let connection = Connection::open(db_file).expect("Failed to open database"); let connection = Connection::open(db_file).expect("Failed to open database");
+13 -7
View File
@@ -1,9 +1,11 @@
use crate::fs::*; use crate::fs::*;
use crate::notification::NotificationData::{CompressError, OpenFileError, PermissionDenied, WebApiUnavailable}; use crate::notification::NotificationData::{
CompressError, OpenFileError, PermissionDenied, WebApiUnavailable,
};
use crate::notification::{MaybeError, NotificationData}; use crate::notification::{MaybeError, NotificationData};
use log::info; use log::info;
use std::io; use std::io;
use tokio::fs::{remove_file, File, OpenOptions}; use tokio::fs::{File, OpenOptions, remove_file};
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use zstd::{DEFAULT_COMPRESSION_LEVEL, Decoder, Encoder}; use zstd::{DEFAULT_COMPRESSION_LEVEL, Decoder, Encoder};
@@ -49,10 +51,10 @@ pub async fn load_data(id: String, temp: bool) -> MaybeError {
.get(&id_url) .get(&id_url)
.send() .send()
.await .await
.map_err(|_| WebApiUnavailable)? .map_err(|e| WebApiUnavailable)?
.bytes() .bytes()
.await .await
.map_err(|_| WebApiUnavailable)? .map_err(|e| WebApiUnavailable)?
.to_vec(); .to_vec();
let data = decompress(data)?; let data = decompress(data)?;
@@ -62,7 +64,7 @@ pub async fn load_data(id: String, temp: bool) -> MaybeError {
tokio::fs::write(db_file, data) tokio::fs::write(db_file, data)
.await .await
.map_err(|_| PermissionDenied)?; .map_err(|e| PermissionDenied)?;
let version_url = format!("{API_URL}{id}/version"); let version_url = format!("{API_URL}{id}/version");
let version = client let version = client
@@ -74,8 +76,12 @@ pub async fn load_data(id: String, temp: bool) -> MaybeError {
.await .await
.map_err(|_| WebApiUnavailable)?; .map_err(|_| WebApiUnavailable)?;
set_local_version(version.parse::<u32>().unwrap_or_default()).await?; set_local_version(version.parse::<u32>().unwrap_or_default()).await?;
remove_file(db_wal()).await.map_err(|_| OpenFileError)?; if db_wal().exists() {
remove_file(db_wal()).await.map_err(|_| OpenFileError)?; remove_file(db_wal()).await.map_err(|_| OpenFileError)?;
}
if db_shm().exists() {
remove_file(db_shm()).await.map_err(|_| OpenFileError)?;
}
Ok(()) Ok(())
} }
+6 -2
View File
@@ -5,7 +5,7 @@ use crate::data_provider::web_api::*;
use crate::jl_button; use crate::jl_button;
use crate::navigation::Page::PreviousPage; use crate::navigation::Page::PreviousPage;
use crate::navigation::{NavigatedPage, Page, RootMessage}; use crate::navigation::{NavigatedPage, Page, RootMessage};
use crate::notification::{NotificationData, NotificationRequest}; use crate::notification::{MaybeError, NotificationData, NotificationRequest};
use crate::pages::sync::SyncMessage::*; use crate::pages::sync::SyncMessage::*;
use crate::styling::*; use crate::styling::*;
use crate::{push_error, push_error_task}; use crate::{push_error, push_error_task};
@@ -115,12 +115,16 @@ impl NavigatedPage<SyncMessage> for SyncState {
self.real_load = false; self.real_load = false;
let id = self.state.sync_data.read().key.clone().unwrap(); let id = self.state.sync_data.read().key.clone().unwrap();
self.state.connection.lock().finish();
let tasks = Task::batch([ let tasks = Task::batch([
Task::perform( Task::perform(
async { tokio::time::sleep(Duration::from_millis(200)).await }, async { tokio::time::sleep(Duration::from_millis(200)).await },
|_| RootMessage::Sync(NextAnimation), |_| RootMessage::Sync(NextAnimation),
), ),
Task::perform(load_data(id, false), |_| RootMessage::Sync(NetworkFinished)), Task::perform(load_data(id, false), |load_result| match load_result {
Ok(_) => RootMessage::Sync(NetworkFinished),
Err(error) => push_error!(error)
}),
]); ]);
return tasks; return tasks;
+13 -8
View File
@@ -1,7 +1,9 @@
use crate::data::entities::{CustomField, DeckSettings, WordData}; use crate::data::entities::{CustomField, DeckSettings, WordData};
use crate::data::Id; use crate::data::Id;
use iced::widget::{button, center, column, rule, space, text}; use iced::widget::{button, center, column, rule, space, text};
use iced_core::Alignment::Center;
use iced_core::Length::Fill; use iced_core::Length::Fill;
use crate::styling::HALF_SPACING;
pub fn word_display<'a, T: 'a + Clone>( pub fn word_display<'a, T: 'a + Clone>(
deck: &DeckSettings, deck: &DeckSettings,
@@ -64,9 +66,9 @@ fn property_draw<'a, T: 'a + Clone>(
for part in parts { for part in parts {
println!("displaying {}", part); println!("displaying {}", part);
match part { match part {
"key" => column = column.push(text!("{}", word.key).size(48)), "key" => column = column.push(text!("{}", word.key).align_x(Center).size(48)),
"value" => column = column.push(text!("{}", word.value).size(28)), "value" => column = column.push(text!("{}", word.value).align_x(Center).size(28)),
"tags" => column = column.push(text!("{}", word.tags).size(28)), "tags" => column = column.push(text!("{}", word.tags).align_x(Center).size(28)),
"speech" => { "speech" => {
column = column.push(button("Воспроизвести").on_press(speech_action.clone())) column = column.push(button("Воспроизвести").on_press(speech_action.clone()))
} }
@@ -74,29 +76,32 @@ fn property_draw<'a, T: 'a + Clone>(
if part == "reading" if part == "reading"
&& let Some(reading) = word.additional.get(&Id(1)) && let Some(reading) = word.additional.get(&Id(1))
{ {
column = column.push(text!("{}", reading).size(24)) column = column.push(text!("{}", reading).align_x(Center).size(24));
continue
} }
if part == "description" if part == "description"
&& let Some(description) = word.additional.get(&Id(2)) && let Some(description) = word.additional.get(&Id(2))
{ {
column = column.push(text!("{}", description).size(20)) column = column.push(text!("{}", description).align_x(Center).size(20));
continue
} }
if part == "context" if part == "context"
&& let Some(context) = word.additional.get(&Id(3)) && let Some(context) = word.additional.get(&Id(3))
{ {
column = column.push(text!("{}", context).size(24)) column = column.push(text!("{}", context).align_x(Center).size(24));
continue
} }
let field_id = fields_set.iter().find(|f| f.identifier == part); let field_id = fields_set.iter().find(|f| f.identifier == part);
if let Some(id) = field_id if let Some(id) = field_id
&& let Some(custom) = word.additional.get(&id.id) && let Some(custom) = word.additional.get(&id.id)
{ {
column = column.push(text!("{}", custom).size(24)) column = column.push(text!("{}", custom).align_x(Center).size(24))
} }
} }
} }
} }
column.into() column.align_x(Center).spacing(HALF_SPACING).into()
} }