From 5b2b48c88f59b939b050509f01718b865a2d39bf Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Sat, 3 Oct 2026 20:32:11 +0300 Subject: [PATCH] updated card display --- src/pages/repetition.rs | 97 ++++------------------------------ src/widgets/card_display.rs | 102 ++++++++++++++++++++++++++++++++++++ src/widgets/mod.rs | 1 + 3 files changed, 114 insertions(+), 86 deletions(-) create mode 100644 src/widgets/card_display.rs diff --git a/src/pages/repetition.rs b/src/pages/repetition.rs index 8fb007b..5e11614 100644 --- a/src/pages/repetition.rs +++ b/src/pages/repetition.rs @@ -1,22 +1,22 @@ use crate::app::AppState; use crate::core::deck::DeckData; use crate::core::srs::WordOpenMode; -use crate::data::Id; -use crate::data::entities::{CardState, WordData}; +use crate::data::entities::{CardState, CustomField, WordData}; use crate::data::repositories::Repository; +use crate::data::Id; use crate::data_provider::voice::get_voice; -use crate::jl_button; use crate::navigation::Page::PreviousPage; use crate::navigation::{KeyPressedPage, NavigatedPage, Page, RootMessage}; use crate::notification::{MaybeError, NotificationData}; +use crate::pages::repetition::RepetitionMessage::Play; use crate::pages::repetitions::DeckRunData; use crate::styling::*; use crate::{push_error, push_error_task}; use iced::alignment::Horizontal::Center; use iced::keyboard::key::Physical::Code; use iced::widget::text::Style; -use iced::widget::{Column, button, column, container, row, rule, space, text, tooltip}; -use iced::{Element, Fill, Task, Theme, alignment, keyboard}; +use iced::widget::{button, column, container, row, text, tooltip}; +use iced::{keyboard, Element, Fill, Task, Theme}; use rodio::MixerDeviceSink; use std::collections::HashSet; use std::sync::Arc; @@ -32,6 +32,7 @@ pub struct RepetitionState { can_play: bool, sink: Arc>, opened: HashSet, + custom_fields_cache: Vec, } impl NavigatedPage for RepetitionState { @@ -73,17 +74,7 @@ impl NavigatedPage for RepetitionState { fn view(&self) -> Element<'_, RepetitionMessage> { back_overlay( column![ - container(self.draw_forward()) - .width(Fill) - .height(Fill) - .align_x(Center) - .align_y(alignment::Vertical::Center), - rule::horizontal(2), - container(self.draw_backward()) - .width(Fill) - .height(Fill) - .align_x(Center) - .align_y(alignment::Vertical::Center), + crate::widgets::card_display::word_display(&self.settings.general_settings, &self.current_word, self.open, Play, self.custom_fields_cache.as_slice()), container(self.answer_bar()) .width(Fill) .align_x(Center) @@ -92,7 +83,7 @@ impl NavigatedPage for RepetitionState { "Затронуто слов {}, {}%", self.opened.len(), (self.opened.len() as f32 / self.set.len() as f32 * 10000.0).round() / 100.0 - ) + ), ] .height(Fill) .width(Fill) @@ -117,6 +108,8 @@ impl RepetitionState { None }; + let custom_fields_cache = state.custom_fields.read().iter().cloned().collect(); + Ok(RepetitionState { state, settings: set, @@ -127,6 +120,7 @@ impl RepetitionState { can_play: true, sink: Arc::new(sink_handle), opened: HashSet::new(), + custom_fields_cache, }) } } @@ -169,43 +163,6 @@ impl RepetitionState { Task::none() } - fn draw_forward(&self) -> Element<'_, RepetitionMessage> { - self.draw_card_view(self.settings.forward.as_str()) - } - - fn draw_backward(&self) -> Element<'_, RepetitionMessage> { - if !self.open { - return container(text!("?").size(72)) - .width(Fill) - .height(Fill) - .align_y(alignment::Vertical::Center) - .align_x(Center) - .into(); - } - - self.draw_card_view(self.settings.backward.as_str()) - } - - fn draw_card_view(&self, properties: &str) -> Element<'_, RepetitionMessage> { - let word = &self.current_word; - - let mut col = Column::new(); - - for view_type in properties.split(" ") { - col = col.push(match view_type { - "key" => self.draw_key(word), - "value" => self.draw_value(word), - "speech" => self.draw_voice(), - "reading" => self.draw_reading(word), - "context" => self.draw_context(word), - "description" => self.draw_description(word), - _ => space().into(), - }) - } - - col.spacing(DEFAULT_SPACING).align_x(Center).into() - } - fn answer_bar(&self) -> Element<'_, RepetitionMessage> { if !self.open { return text!("Нажмите Пробел для открытия карточки") @@ -247,38 +204,6 @@ impl RepetitionState { .spacing(DEFAULT_SPACING) .into() } - - fn draw_key(&self, word: &WordData) -> Element<'_, RepetitionMessage> { - text!("{}", word.key).size(36).into() - } - fn draw_value(&self, word: &WordData) -> Element<'_, RepetitionMessage> { - text!("{}", word.value).size(24).into() - } - - fn draw_voice(&self) -> Element<'_, RepetitionMessage> { - jl_button!("Воспроизвести") - .on_press(RepetitionMessage::Play) - .into() - } - - fn draw_reading(&self, word: &WordData) -> Element<'_, RepetitionMessage> { - 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(&Id(3)) { - None => space().into(), - Some(context) => text!("{}", context).center().size(24).into(), - } - } - fn draw_description(&self, word: &WordData) -> Element<'_, RepetitionMessage> { - match word.additional.get(&Id(2)) { - None => space().into(), - Some(context) => text!("{}", context).center().size(24).into(), - } - } } impl KeyPressedPage for RepetitionState { diff --git a/src/widgets/card_display.rs b/src/widgets/card_display.rs new file mode 100644 index 0000000..cfbdd6c --- /dev/null +++ b/src/widgets/card_display.rs @@ -0,0 +1,102 @@ +use crate::data::entities::{CustomField, DeckSettings, WordData}; +use crate::data::Id; +use iced::widget::{button, center, column, rule, space, text}; +use iced_core::Length::Fill; + +pub fn word_display<'a, T: 'a + Clone>( + deck: &DeckSettings, + word: &WordData, + open: bool, + speech_action: T, + fields_set: &[CustomField], +) -> iced::Element<'a, T> { + column![ + forward_side(deck, word, speech_action.clone(), fields_set), + rule::horizontal(2), + backward_side(deck, word, speech_action, fields_set, open) + ] + .into() +} + +fn forward_side<'a, T: 'a + Clone>( + deck: &DeckSettings, + word: &WordData, + speech_action: T, + fields_set: &[CustomField], +) -> iced::Element<'a, T> { + center(property_draw( + deck.forward.as_str(), + word, + speech_action, + fields_set, + )) + .into() +} + +fn backward_side<'a, T: 'a + Clone>( + deck: &DeckSettings, + word: &WordData, + speech_action: T, + fields_set: &[CustomField], + open: bool, +) -> iced::Element<'a, T> { + if open { + return center(property_draw( + deck.backward.as_str(), + word, + speech_action, + fields_set, + )) + .into(); + } + center(text!("?").size(72)).width(Fill).height(Fill).into() +} + +fn property_draw<'a, T: 'a + Clone>( + formula: &str, + word: &WordData, + speech_action: T, + fields_set: &[CustomField], +) -> iced::Element<'a, T> { + let mut column = column![]; + let parts = formula.split(" "); + println!("{:?}", formula); + for part in parts { + println!("displaying {}", part); + match part { + "key" => column = column.push(text!("{}", word.key).size(48)), + "value" => column = column.push(text!("{}", word.value).size(28)), + "tags" => column = column.push(text!("{}", word.tags).size(28)), + "speech" => { + column = column.push(button("Воспроизвести").on_press(speech_action.clone())) + } + _ => { + if part == "reading" + && let Some(reading) = word.additional.get(&Id(1)) + { + column = column.push(text!("{}", reading).size(24)) + } + + if part == "description" + && let Some(description) = word.additional.get(&Id(2)) + { + column = column.push(text!("{}", description).size(20)) + } + + if part == "context" + && let Some(context) = word.additional.get(&Id(3)) + { + column = column.push(text!("{}", context).size(24)) + } + + let field_id = fields_set.iter().find(|f| f.identifier == part); + if let Some(id) = field_id + && let Some(custom) = word.additional.get(&id.id) + { + column = column.push(text!("{}", custom).size(24)) + } + } + } + } + column.into() +} diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 63b5cf6..5b297c0 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1 +1,2 @@ pub mod hard_mouse_area; +pub mod card_display;