Exams page more code
This commit is contained in:
1 parent
4b9e257cdf
commit
79c42d0feb
6 files changed
+391
-17
No files matched your search
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
create table exam_entry
|
create table exam_entries
|
||||||
(
|
(
|
||||||
id integer primary key,
|
id integer primary key,
|
||||||
exam_id integer not null references exam on delete cascade,
|
exam_id integer not null references exams on delete cascade,
|
||||||
word_id integer not null references words on delete cascade,
|
word_id integer not null references words on delete cascade,
|
||||||
status integer default null
|
status integer default null
|
||||||
);
|
);
|
||||||
@@ -64,19 +64,19 @@ pub struct ExamEntryQuerySet;
|
|||||||
|
|
||||||
impl TableAccessQuerySet<ExamEntry> for ExamEntryQuerySet {
|
impl TableAccessQuerySet<ExamEntry> for ExamEntryQuerySet {
|
||||||
fn load() -> &'static str {
|
fn load() -> &'static str {
|
||||||
"SELECT id, exam_id, word_id, status FROM exam_entry"
|
"SELECT id, exam_id, word_id, status FROM exam_entries"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save() -> &'static str {
|
fn save() -> &'static str {
|
||||||
"UPDATE exam_entry set status = $1 WHERE id = $2"
|
"UPDATE exam_entries set status = $1 WHERE id = $2"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add() -> &'static str {
|
fn add() -> &'static str {
|
||||||
"INSERT into exam_entry (exam_id, word_id, status) VALUES ($1, $2, $3)"
|
"INSERT into exam_entries (exam_id, word_id, status) VALUES ($1, $2, $3)"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name() -> &'static str {
|
fn name() -> &'static str {
|
||||||
"exam_entry"
|
"exam_entries"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_sql(row: &Row) -> Result<ExamEntry, Error> {
|
fn from_sql(row: &Row) -> Result<ExamEntry, Error> {
|
||||||
|
|||||||
+10
-4
@@ -1,4 +1,4 @@
|
|||||||
use crate::app::{AppState, fill_state};
|
use crate::app::{fill_state, AppState};
|
||||||
use crate::data_provider::sqlite::create_db;
|
use crate::data_provider::sqlite::create_db;
|
||||||
use crate::data_provider::web_api::{
|
use crate::data_provider::web_api::{
|
||||||
get_local_version, get_web_version, load_data, set_local_version,
|
get_local_version, get_web_version, load_data, set_local_version,
|
||||||
@@ -12,6 +12,7 @@ use crate::notification::{
|
|||||||
};
|
};
|
||||||
use crate::pages::dictionary::{DictionaryMessage, DictionaryState};
|
use crate::pages::dictionary::{DictionaryMessage, DictionaryState};
|
||||||
use crate::pages::dictionary_quiz::{DictionaryQuizMessage, DictionaryQuizState};
|
use crate::pages::dictionary_quiz::{DictionaryQuizMessage, DictionaryQuizState};
|
||||||
|
use crate::pages::exams::{ExamsMessage, ExamsState};
|
||||||
use crate::pages::history::{HistoryMessage, HistoryState};
|
use crate::pages::history::{HistoryMessage, HistoryState};
|
||||||
use crate::pages::import::{ImportMessage, ImportState};
|
use crate::pages::import::{ImportMessage, ImportState};
|
||||||
use crate::pages::quiz::{QuizMessage, QuizState};
|
use crate::pages::quiz::{QuizMessage, QuizState};
|
||||||
@@ -59,6 +60,7 @@ pub enum RootMessage {
|
|||||||
History(HistoryMessage),
|
History(HistoryMessage),
|
||||||
RepetitionSettings(RepetitionSettingsMessage),
|
RepetitionSettings(RepetitionSettingsMessage),
|
||||||
Import(ImportMessage),
|
Import(ImportMessage),
|
||||||
|
Exams(ExamsMessage),
|
||||||
Keyboard(Event),
|
Keyboard(Event),
|
||||||
PushNotification(NotificationRequest),
|
PushNotification(NotificationRequest),
|
||||||
Notification(NotificationMessage),
|
Notification(NotificationMessage),
|
||||||
@@ -80,6 +82,7 @@ pub enum Page {
|
|||||||
History(HistoryState),
|
History(HistoryState),
|
||||||
RepetitionSettings(RepetitionSettingsState),
|
RepetitionSettings(RepetitionSettingsState),
|
||||||
Import(ImportState),
|
Import(ImportState),
|
||||||
|
Exams(ExamsState),
|
||||||
PreviousPage,
|
PreviousPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +185,8 @@ impl ScreenState {
|
|||||||
Sync,
|
Sync,
|
||||||
History,
|
History,
|
||||||
RepetitionSettings,
|
RepetitionSettings,
|
||||||
Import
|
Import,
|
||||||
|
Exams
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
debug!("Update took {:?}", time.elapsed());
|
debug!("Update took {:?}", time.elapsed());
|
||||||
@@ -205,7 +209,8 @@ impl ScreenState {
|
|||||||
Sync,
|
Sync,
|
||||||
History,
|
History,
|
||||||
RepetitionSettings,
|
RepetitionSettings,
|
||||||
Import
|
Import,
|
||||||
|
Exams
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +230,8 @@ impl ScreenState {
|
|||||||
Sync,
|
Sync,
|
||||||
History,
|
History,
|
||||||
RepetitionSettings,
|
RepetitionSettings,
|
||||||
Import
|
Import,
|
||||||
|
Exams
|
||||||
);
|
);
|
||||||
|
|
||||||
let notifications = self.notification_manager.draw().map(Notification);
|
let notifications = self.notification_manager.draw().map(Notification);
|
||||||
|
|||||||
@@ -11,3 +11,4 @@ pub mod selector;
|
|||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod word;
|
pub mod word;
|
||||||
pub mod writing;
|
pub mod writing;
|
||||||
|
pub mod exams;
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
use crate::app::AppState;
|
||||||
|
use crate::data::entities::{DeckSettings, EntityHandle, Exam, ExamEntry};
|
||||||
|
use crate::data::repositories::{BatchedRepository, Repository};
|
||||||
|
use crate::data::Id;
|
||||||
|
use crate::navigation::Page::PreviousPage;
|
||||||
|
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||||
|
use crate::notification::MaybeError;
|
||||||
|
use crate::pages::exams::ExamsMessage::*;
|
||||||
|
use crate::pages::repetitions::Style;
|
||||||
|
use crate::push_error;
|
||||||
|
use crate::styling::{back_overlay, BUTTON_RADIUS, DEFAULT_SPACING, HALF_SPACING};
|
||||||
|
use crate::{jl_button, push_error_task};
|
||||||
|
use chrono::Utc;
|
||||||
|
use iced::widget::button::Status;
|
||||||
|
use iced::widget::{
|
||||||
|
button, center_x, column, container, row, scrollable, space, text, tooltip, Column,
|
||||||
|
};
|
||||||
|
use iced::{Element, Task};
|
||||||
|
use iced_core::Alignment::*;
|
||||||
|
use iced_core::Length::{Fill, FillPortion};
|
||||||
|
use iced_core::{Background, Border, Color, Shadow, Theme};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct ExamsState {
|
||||||
|
state: AppState,
|
||||||
|
deck_id: EntityHandle<DeckSettings>,
|
||||||
|
deck: DeckSettings,
|
||||||
|
selected_exam_id: Option<EntityHandle<Exam>>,
|
||||||
|
exams: BTreeMap<EntityHandle<Exam>, ExamExtended>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
|
pub enum ExamsMessage {
|
||||||
|
Back,
|
||||||
|
SelectExam(EntityHandle<Exam>),
|
||||||
|
DeleteExam(EntityHandle<Exam>),
|
||||||
|
CreateExam,
|
||||||
|
GotoExam,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NavigatedPage<ExamsMessage> for ExamsState {
|
||||||
|
fn navigate(&mut self, message: &ExamsMessage) -> Option<Page> {
|
||||||
|
if let Back = message {
|
||||||
|
return Some(PreviousPage);
|
||||||
|
}
|
||||||
|
if let Some(selected_exam_id) = self.selected_exam_id
|
||||||
|
&& GotoExam == *message
|
||||||
|
{
|
||||||
|
return Some(PreviousPage);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn navigated(&mut self) {}
|
||||||
|
|
||||||
|
fn update(&mut self, message: ExamsMessage) -> Task<RootMessage> {
|
||||||
|
match message {
|
||||||
|
Back => {}
|
||||||
|
GotoExam => {}
|
||||||
|
SelectExam(id) => {
|
||||||
|
self.selected_exam_id = Some(id);
|
||||||
|
}
|
||||||
|
DeleteExam(id) => {
|
||||||
|
self.selected_exam_id = None;
|
||||||
|
}
|
||||||
|
CreateExam => {
|
||||||
|
let exam = Exam {
|
||||||
|
id: Default::default(),
|
||||||
|
timestamp: Utc::now(),
|
||||||
|
deck_id: self.deck_id.id,
|
||||||
|
};
|
||||||
|
let mut exam_repo = self.state.exam.write();
|
||||||
|
let handle = exam_repo.create_now(exam);
|
||||||
|
if let Ok(handle) = handle {
|
||||||
|
drop(exam_repo);
|
||||||
|
if let Err(err) = self.append_exam_entries(handle) {
|
||||||
|
return push_error_task!(err);
|
||||||
|
}
|
||||||
|
self.exams = Self::get_exams_list(&self.state, self.deck_id.id);
|
||||||
|
self.selected_exam_id = Some(handle);
|
||||||
|
} else {
|
||||||
|
return push_error_task!(handle.err().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> Element<'_, ExamsMessage> {
|
||||||
|
back_overlay(
|
||||||
|
column![
|
||||||
|
text(format!("Экзамены для колоды {}", self.deck.name)),
|
||||||
|
row![row![
|
||||||
|
column![
|
||||||
|
scrollable(self.exams_list()).height(Fill),
|
||||||
|
jl_button!("Добавить").width(Fill).on_press(CreateExam),
|
||||||
|
]
|
||||||
|
.spacing(DEFAULT_SPACING)
|
||||||
|
.width(FillPortion(1)),
|
||||||
|
self.selected_exam_view(),
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
Back,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExamsState {
|
||||||
|
pub fn new(deck_id: EntityHandle<DeckSettings>, state: AppState) -> Self {
|
||||||
|
let deck = state.decks.read().get_static(deck_id).unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
exams: Self::get_exams_list(&state, deck_id.id),
|
||||||
|
state,
|
||||||
|
deck_id,
|
||||||
|
deck,
|
||||||
|
selected_exam_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_exam(&self) -> Option<&ExamExtended> {
|
||||||
|
self.exams.get(&self.selected_exam_id?)
|
||||||
|
}
|
||||||
|
fn selected_exam_mut(&mut self) -> Option<&mut ExamExtended> {
|
||||||
|
self.exams.get_mut(&self.selected_exam_id?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append_exam_entries(&mut self, handle: EntityHandle<Exam>) -> MaybeError {
|
||||||
|
let deck_id = self.deck_id.id;
|
||||||
|
let words: Vec<_> = self
|
||||||
|
.state
|
||||||
|
.card_states
|
||||||
|
.read()
|
||||||
|
.iter()
|
||||||
|
.filter(|state| state.deck_id == deck_id)
|
||||||
|
.map(|state| state.word_id)
|
||||||
|
.collect();
|
||||||
|
let mut entries = words
|
||||||
|
.iter()
|
||||||
|
.map(|word_id| ExamEntry {
|
||||||
|
id: Default::default(),
|
||||||
|
exam_id: handle.id,
|
||||||
|
word_id: *word_id,
|
||||||
|
status: None,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
self.state
|
||||||
|
.exam_entries
|
||||||
|
.write()
|
||||||
|
.create_now_many(entries.as_mut_slice())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_exams_list(state: &AppState, deck_id: Id) -> BTreeMap<EntityHandle<Exam>, ExamExtended> {
|
||||||
|
let mut query = state
|
||||||
|
.exam
|
||||||
|
.read()
|
||||||
|
.query(Arc::new(move |exam| exam.deck_id == deck_id));
|
||||||
|
let handles: Vec<_> = query.handles().collect();
|
||||||
|
query
|
||||||
|
.iter(&state.exam.read())
|
||||||
|
.cloned()
|
||||||
|
.zip(handles)
|
||||||
|
.map(|(e, h)| (h, ExamExtended::from(e, &state)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExamsState {
|
||||||
|
pub fn exams_list(&self) -> Column<'_, ExamsMessage> {
|
||||||
|
let mut column = Column::new();
|
||||||
|
|
||||||
|
for (handle, deck) in self.exams.iter() {
|
||||||
|
column = column.push(
|
||||||
|
button(text!("{}", &deck.timestamp.format("%d/%m/%Y %H:%M")))
|
||||||
|
.on_press_with(move || SelectExam(*handle))
|
||||||
|
.style(move |_x: &Theme, status: Status| Style {
|
||||||
|
background: if status == Status::Hovered {
|
||||||
|
Some(Background::Color(Color::WHITE.scale_alpha(0.2)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
text_color: _x.palette().primary,
|
||||||
|
border: Border {
|
||||||
|
color: Default::default(),
|
||||||
|
width: 0.0,
|
||||||
|
radius: BUTTON_RADIUS.into(),
|
||||||
|
},
|
||||||
|
shadow: Shadow::default(),
|
||||||
|
snap: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
column
|
||||||
|
}
|
||||||
|
pub fn selected_exam_view(&self) -> Element<'_, ExamsMessage> {
|
||||||
|
if let Some(exam) = self.selected_exam() {
|
||||||
|
return column![
|
||||||
|
center_x(text!(
|
||||||
|
"Экзамен от {}",
|
||||||
|
exam.timestamp.format("%d/%m/%Y %H:%M")
|
||||||
|
)),
|
||||||
|
row![text!("{} карточек", exam.total), Self::exam_bar(exam)]
|
||||||
|
.height(30)
|
||||||
|
.align_y(Center)
|
||||||
|
.width(Fill).spacing(HALF_SPACING),
|
||||||
|
self.exam_variable_view(exam),
|
||||||
|
]
|
||||||
|
.spacing(DEFAULT_SPACING)
|
||||||
|
.width(FillPortion(2))
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
space().width(FillPortion(3)).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exam_bar(exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
||||||
|
let total = 1000.0;
|
||||||
|
let answered = exam.answered as f64 / exam.total as f64 * total;
|
||||||
|
let unknown = exam.unknown as f64 / exam.total as f64 * total;
|
||||||
|
let remaining = exam.remaining() as f64 / exam.total as f64 * total;
|
||||||
|
row![
|
||||||
|
tooltip(
|
||||||
|
container(space())
|
||||||
|
.height(Fill)
|
||||||
|
.width(FillPortion(answered as u16))
|
||||||
|
.style(|theme: &Theme| {
|
||||||
|
container::Style {
|
||||||
|
background: Some(Background::Color(theme.palette().success)),
|
||||||
|
text_color: Default::default(),
|
||||||
|
border: Default::default(),
|
||||||
|
shadow: Default::default(),
|
||||||
|
snap: false,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
text!("Правильно: {}%", answered / 10.0),
|
||||||
|
tooltip::Position::Bottom
|
||||||
|
),
|
||||||
|
tooltip(
|
||||||
|
container(space())
|
||||||
|
.height(Fill)
|
||||||
|
.width(FillPortion(unknown as u16))
|
||||||
|
.style(|theme: &Theme| {
|
||||||
|
container::Style {
|
||||||
|
background: Some(Background::Color(theme.palette().danger)),
|
||||||
|
text_color: Default::default(),
|
||||||
|
border: Default::default(),
|
||||||
|
shadow: Default::default(),
|
||||||
|
snap: false,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
text!("Не получилось: {}%", unknown / 10.0),
|
||||||
|
tooltip::Position::Bottom
|
||||||
|
),
|
||||||
|
tooltip(
|
||||||
|
container(space())
|
||||||
|
.height(Fill)
|
||||||
|
.width(FillPortion(remaining as u16))
|
||||||
|
.style(|theme: &Theme| {
|
||||||
|
container::Style {
|
||||||
|
background: Some(Background::Color(theme.palette().primary)),
|
||||||
|
text_color: Default::default(),
|
||||||
|
border: Default::default(),
|
||||||
|
shadow: Default::default(),
|
||||||
|
snap: false,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
text!("Осталось {}%", remaining / 10.0),
|
||||||
|
tooltip::Position::Bottom
|
||||||
|
)
|
||||||
|
]
|
||||||
|
.width(Fill)
|
||||||
|
.height(Fill)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exam_variable_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
||||||
|
if exam.finished() {
|
||||||
|
self.exam_finished_view(exam)
|
||||||
|
} else {
|
||||||
|
self.exam_ongoing_view(exam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exam_finished_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
||||||
|
column![].spacing(DEFAULT_SPACING).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exam_ongoing_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
||||||
|
center_x(button("Продолжить экзамен").on_press(GotoExam)).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExamExtended {
|
||||||
|
exam: Exam,
|
||||||
|
total: u32,
|
||||||
|
answered: u32,
|
||||||
|
unknown: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExamExtended {
|
||||||
|
fn from(exam: Exam, state: &AppState) -> Self {
|
||||||
|
let entries = state.exam_entries.read();
|
||||||
|
let mut total = 0;
|
||||||
|
let mut answered = 0;
|
||||||
|
let mut unknown = 0;
|
||||||
|
entries.iter().filter(|e| e.exam_id == e.id).for_each(|e| {
|
||||||
|
total += 1;
|
||||||
|
match e.status {
|
||||||
|
None => {}
|
||||||
|
Some(s) => {
|
||||||
|
if s {
|
||||||
|
answered += 1;
|
||||||
|
} else {
|
||||||
|
unknown += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
exam,
|
||||||
|
|
||||||
|
total,
|
||||||
|
answered,
|
||||||
|
unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn solved(&self) -> u32 {
|
||||||
|
self.answered + self.unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finished(&self) -> bool {
|
||||||
|
self.solved() == self.total
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remaining(&self) -> u32 {
|
||||||
|
self.total - self.solved()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ExamExtended {
|
||||||
|
type Target = Exam;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.exam
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for ExamExtended {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.exam
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,10 @@ use crate::core::deck::DeckData;
|
|||||||
use crate::core::srs::{AppendMode, OrderMode};
|
use crate::core::srs::{AppendMode, OrderMode};
|
||||||
use crate::data::entities::{CardState, DeckSettings, EntityHandle, WordData};
|
use crate::data::entities::{CardState, DeckSettings, EntityHandle, WordData};
|
||||||
use crate::data::repositories::{BatchedRepository, Repository};
|
use crate::data::repositories::{BatchedRepository, Repository};
|
||||||
use crate::navigation::Page::{History, PreviousPage, Repetition, RepetitionSettings};
|
use crate::navigation::Page::{Exams, History, PreviousPage, Repetition, RepetitionSettings};
|
||||||
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||||
use crate::notification::MaybeError;
|
use crate::notification::MaybeError;
|
||||||
|
use crate::pages::exams::ExamsState;
|
||||||
use crate::pages::history::HistoryState;
|
use crate::pages::history::HistoryState;
|
||||||
use crate::pages::repetition::RepetitionState;
|
use crate::pages::repetition::RepetitionState;
|
||||||
use crate::pages::repetition_settings::RepetitionSettingsState;
|
use crate::pages::repetition_settings::RepetitionSettingsState;
|
||||||
@@ -16,17 +17,16 @@ use crate::styling::*;
|
|||||||
use crate::{jl_button, jl_text_input};
|
use crate::{jl_button, jl_text_input};
|
||||||
use chrono::{Days, Local, Utc};
|
use chrono::{Days, Local, Utc};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
use iced::widget::button::{danger, Status};
|
||||||
pub use iced::widget::button::{Catalog, Style};
|
pub use iced::widget::button::{Catalog, Style};
|
||||||
use iced::widget::button::{Status, danger};
|
|
||||||
use iced::widget::tooltip::Position::Top;
|
use iced::widget::tooltip::Position::Top;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
Column, Row, button, column, container, lazy, radio, row, scrollable, space, svg, text,
|
button, column, container, lazy, radio, row, scrollable, space, svg, text, tooltip, Column, Row,
|
||||||
text_input, tooltip,
|
|
||||||
};
|
};
|
||||||
use iced::{Background, Border, Center, Color, Element, Fill, Length, Shadow, Task, Theme};
|
use iced::{Background, Border, Center, Color, Element, Fill, Length, Shadow, Task, Theme};
|
||||||
use iced_core::Padding;
|
|
||||||
use iced_core::border::Radius;
|
use iced_core::border::Radius;
|
||||||
use iced_core::svg::Handle;
|
use iced_core::svg::Handle;
|
||||||
|
use iced_core::Padding;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -74,7 +74,10 @@ impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
|||||||
self.selected_deck_handle.unwrap(),
|
self.selected_deck_handle.unwrap(),
|
||||||
self.state.clone(),
|
self.state.clone(),
|
||||||
)))
|
)))
|
||||||
} else {
|
} else if let GoToExams = message {
|
||||||
|
Some(Exams(ExamsState::new(self.selected_deck_handle.unwrap(), self.state.clone())))
|
||||||
|
} else
|
||||||
|
{
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,6 +222,7 @@ impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
|||||||
return push_error_task!(err);
|
return push_error_task!(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GoToExams => {}
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
@@ -355,7 +359,10 @@ impl RepetitionsState {
|
|||||||
Some(deck.open_mode),
|
Some(deck.open_mode),
|
||||||
SetOpenMode
|
SetOpenMode
|
||||||
),
|
),
|
||||||
jl_button!("История").on_press(GoToHistory),
|
row![
|
||||||
|
jl_button!("История").on_press(GoToHistory),
|
||||||
|
jl_button!("Экзамены").on_press(GoToExams),
|
||||||
|
].spacing(DEFAULT_SPACING),
|
||||||
]
|
]
|
||||||
.spacing(HALF_SPACING)
|
.spacing(HALF_SPACING)
|
||||||
}
|
}
|
||||||
@@ -630,6 +637,7 @@ pub enum RepetitionsMessage {
|
|||||||
SetOpenMode(OrderMode),
|
SetOpenMode(OrderMode),
|
||||||
SetAppendMode(AppendMode),
|
SetAppendMode(AppendMode),
|
||||||
GoToHistory,
|
GoToHistory,
|
||||||
|
GoToExams,
|
||||||
GoToSettings,
|
GoToSettings,
|
||||||
AppendWords(usize),
|
AppendWords(usize),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user