Activity map
This commit is contained in:
@@ -21,7 +21,6 @@ use crate::{AppState, fill_state};
|
|||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use iced::keyboard::Event;
|
use iced::keyboard::Event;
|
||||||
use iced::{Element, Task};
|
use iced::{Element, Task};
|
||||||
use rusqlite::fallible_iterator::FallibleIterator;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use tokio::task::spawn_blocking;
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
pub struct RepetitionState {
|
pub struct RepetitionState {
|
||||||
|
state: Arc<Mutex<AppState>>,
|
||||||
pub settings: CardSetSettings,
|
pub settings: CardSetSettings,
|
||||||
pub set: CardSet,
|
pub set: CardSet,
|
||||||
current_word: WordData,
|
current_word: WordData,
|
||||||
@@ -43,6 +44,7 @@ impl RepetitionState {
|
|||||||
let sink_handle = rodio::DeviceSinkBuilder::open_default_sink().unwrap();
|
let sink_handle = rodio::DeviceSinkBuilder::open_default_sink().unwrap();
|
||||||
|
|
||||||
RepetitionState {
|
RepetitionState {
|
||||||
|
state,
|
||||||
settings: set,
|
settings: set,
|
||||||
set: card_set,
|
set: card_set,
|
||||||
current_word: word,
|
current_word: word,
|
||||||
@@ -109,6 +111,7 @@ impl RepetitionState {
|
|||||||
|_| RootMessage::Repetition(RepetitionMessage::PlayFinished),
|
|_| RootMessage::Repetition(RepetitionMessage::PlayFinished),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use crate::AppState;
|
|
||||||
use crate::data_provider::card_sets::{delete_set, update_card_set};
|
use crate::data_provider::card_sets::{delete_set, update_card_set};
|
||||||
use crate::navigation::Page::PreviousPage;
|
use crate::navigation::Page::PreviousPage;
|
||||||
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||||
use crate::repetition_settings::RepetitionSettingsMessage::*;
|
use crate::repetition_settings::RepetitionSettingsMessage::*;
|
||||||
use crate::repetitions::{CardSetSettings, RepetitionsMessage};
|
use crate::repetitions::CardSetSettings;
|
||||||
use crate::styling::*;
|
use crate::styling::*;
|
||||||
|
use crate::AppState;
|
||||||
use iced::widget::button::danger;
|
use iced::widget::button::danger;
|
||||||
use iced::widget::{button, column, row, scrollable, space, text, text_input};
|
use iced::widget::{button, column, row, scrollable, space, text, text_input};
|
||||||
use iced::{Element, Task};
|
use iced::{Element, Task};
|
||||||
use iced_core::Length::Fill;
|
use iced_core::Length::Fill;
|
||||||
use iced_core::{Length, Padding};
|
use iced_core::Padding;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|||||||
+78
-6
@@ -9,11 +9,17 @@ use crate::repetition_settings::RepetitionSettingsState;
|
|||||||
use crate::repetitions::RepetitionsMessage::*;
|
use crate::repetitions::RepetitionsMessage::*;
|
||||||
use crate::styling::*;
|
use crate::styling::*;
|
||||||
use crate::{AppState, RootMessage};
|
use crate::{AppState, RootMessage};
|
||||||
|
use chrono::{Days, Local};
|
||||||
use iced::widget::button::{danger, Status};
|
use iced::widget::button::{danger, Status};
|
||||||
pub use iced::widget::button::{Catalog, Style};
|
pub use iced::widget::button::{Catalog, Style};
|
||||||
use iced::widget::container::bordered_box;
|
use iced::widget::container::bordered_box;
|
||||||
use iced::widget::{button, column, container, radio, row, scrollable, space, svg, text, text_input, Column};
|
use iced::widget::tooltip::Position::Top;
|
||||||
|
use iced::widget::{
|
||||||
|
button, column, container, radio, row, scrollable, space, svg, text, text_input, tooltip, Column,
|
||||||
|
Row,
|
||||||
|
};
|
||||||
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::border::Radius;
|
||||||
use iced_core::svg::Handle;
|
use iced_core::svg::Handle;
|
||||||
use iced_core::Padding;
|
use iced_core::Padding;
|
||||||
use rhai::{Engine, Scope};
|
use rhai::{Engine, Scope};
|
||||||
@@ -156,8 +162,7 @@ impl RepetitionsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn launch_delete_button(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
fn launch_delete_button(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
if set.id != 0
|
if set.id != 0 {
|
||||||
{
|
|
||||||
return row![
|
return row![
|
||||||
space().width(Fill),
|
space().width(Fill),
|
||||||
button(text!("Начать повторение").width(200).center())
|
button(text!("Начать повторение").width(200).center())
|
||||||
@@ -173,10 +178,9 @@ impl RepetitionsState {
|
|||||||
if let Some(index) = self.selected_set {
|
if let Some(index) = self.selected_set {
|
||||||
let set;
|
let set;
|
||||||
{
|
{
|
||||||
|
|
||||||
let state = self.state.lock().unwrap();
|
let state = self.state.lock().unwrap();
|
||||||
if state.card_sets.len() <= index {
|
if state.card_sets.len() <= index {
|
||||||
return space().width(Length::FillPortion(3)).into()
|
return space().width(Length::FillPortion(3)).into();
|
||||||
}
|
}
|
||||||
set = state.card_sets[index].clone();
|
set = state.card_sets[index].clone();
|
||||||
}
|
}
|
||||||
@@ -254,7 +258,75 @@ impl RepetitionsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn filled_set_data_view(&self, set: &CardSetSettings) -> Column<'_, RepetitionsMessage> {
|
fn filled_set_data_view(&self, set: &CardSetSettings) -> Column<'_, RepetitionsMessage> {
|
||||||
column![].spacing(DEFAULT_SPACING).into()
|
column![self.activity_bar(set)].align_x(Center)
|
||||||
|
.width(Fill)
|
||||||
|
.spacing(DEFAULT_SPACING)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn activity_bar(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
|
let state = self.state.lock().unwrap();
|
||||||
|
let history = state.activity.get(&set.id);
|
||||||
|
let mut counts: Vec<u32> = vec![0; 30 * 7];
|
||||||
|
|
||||||
|
let now = Local::now().date_naive();
|
||||||
|
|
||||||
|
if let Some(history) = history {
|
||||||
|
for (date, activity) in history {
|
||||||
|
let distance = *date - now;
|
||||||
|
let index = counts.len() as i64 - distance.num_days() - 1;
|
||||||
|
|
||||||
|
if index < 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
counts[index as usize] = *activity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut row = Row::new()
|
||||||
|
.padding(Padding {
|
||||||
|
top: 0.0,
|
||||||
|
right: 0.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
left: DEFAULT_SPACING,
|
||||||
|
})
|
||||||
|
.spacing(QUARTER_SPACING);
|
||||||
|
|
||||||
|
const MAX_DAY_COUNT: f32 = 128.0;
|
||||||
|
|
||||||
|
let mut iter = counts.into_iter();
|
||||||
|
for i in 0..30 {
|
||||||
|
let mut column = Column::new().spacing(QUARTER_SPACING);
|
||||||
|
|
||||||
|
for j in 0..7 {
|
||||||
|
let value = iter.next().unwrap() as f32;
|
||||||
|
let k = (value / MAX_DAY_COUNT).min(1.0) * 0.9 + 0.1;
|
||||||
|
|
||||||
|
let date = now.clone().checked_sub_days(Days::new(30 * 7 - i * 7 - j - 1)).unwrap();
|
||||||
|
|
||||||
|
column = column.push(tooltip(
|
||||||
|
iced::widget::container(space().height(15).width(15)).style(
|
||||||
|
move |x: &Theme| container::Style {
|
||||||
|
text_color: None,
|
||||||
|
background: Some(Background::Color(x.palette().primary.scale_alpha(k))),
|
||||||
|
border: Border {
|
||||||
|
color: Default::default(),
|
||||||
|
width: 0.0,
|
||||||
|
radius: Radius::new(5),
|
||||||
|
},
|
||||||
|
shadow: Default::default(),
|
||||||
|
snap: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
text!("{} {} карточки", date.format("%Y.%m.%d"), value),
|
||||||
|
Top,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
row = row.push(column);
|
||||||
|
}
|
||||||
|
scrollable(column!["Карта активности", row].spacing(QUARTER_SPACING).align_x(Center)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn words_words_view(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
fn words_words_view(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
|
|||||||
Reference in New Issue
Block a user