diff options
author | Akshay <[email protected]> | 2020-07-12 08:03:58 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2020-07-12 08:03:58 +0100 |
commit | e670dab4826006dda1bccdd05d99a61b4fe2b900 (patch) | |
tree | c4dc48c77b3ac708303e032c08f62cfc4448147f | |
parent | bc81cf4d3f0847bdf64974ad91f60c293b4f6a77 (diff) |
add new mode: week view mode
accessible via 'v' (single habit week mode toggle) and 'V' (bulk week
mode) from any mode, press 'esc' to go back to day mode (this is
probably the 'normal' mode of dijo)
-rw-r--r-- | src/app.rs | 29 | ||||
-rw-r--r-- | src/views.rs | 85 |
2 files changed, 82 insertions, 32 deletions
@@ -111,7 +111,7 @@ impl App { | |||
111 | fn status(&self) -> StatusLine { | 111 | fn status(&self) -> StatusLine { |
112 | let today = chrono::Local::now().naive_utc().date(); | 112 | let today = chrono::Local::now().naive_utc().date(); |
113 | let remaining = self.habits.iter().map(|h| h.remaining(today)).sum::<u32>(); | 113 | let remaining = self.habits.iter().map(|h| h.remaining(today)).sum::<u32>(); |
114 | let total = self.habits.iter().map(|h| h.total()).sum::<u32>(); | 114 | let total = self.habits.iter().map(|h| h.goal()).sum::<u32>(); |
115 | let completed = total - remaining; | 115 | let completed = total - remaining; |
116 | 116 | ||
117 | let timestamp = if self.view_month_offset == 0 { | 117 | let timestamp = if self.view_month_offset == 0 { |
@@ -124,7 +124,7 @@ impl App { | |||
124 | let months = self.view_month_offset; | 124 | let months = self.view_month_offset; |
125 | format!( | 125 | format!( |
126 | "{:>width$}", | 126 | "{:>width$}", |
127 | format!("{} months ago", self.view_month_offset), | 127 | format!("{} months ago", months), |
128 | width = CONFIGURATION.view_width * CONFIGURATION.grid_width | 128 | width = CONFIGURATION.view_width * CONFIGURATION.grid_width |
129 | ) | 129 | ) |
130 | }; | 130 | }; |
@@ -226,7 +226,7 @@ impl View for App { | |||
226 | let view_height = CONFIGURATION.view_height; | 226 | let view_height = CONFIGURATION.view_height; |
227 | let width = { | 227 | let width = { |
228 | if self.habits.len() > 0 { | 228 | if self.habits.len() > 0 { |
229 | grid_width * view_width | 229 | grid_width * (view_width + 2) |
230 | } else { | 230 | } else { |
231 | 0 | 231 | 0 |
232 | } | 232 | } |
@@ -283,6 +283,29 @@ impl View for App { | |||
283 | self.save_state(); | 283 | self.save_state(); |
284 | return EventResult::with_cb(|s| s.quit()); | 284 | return EventResult::with_cb(|s| s.quit()); |
285 | } | 285 | } |
286 | Event::Char('v') => { | ||
287 | if self.habits.is_empty() { | ||
288 | return EventResult::Consumed(None); | ||
289 | } | ||
290 | if self.habits[self.focus].view_mode() == ViewMode::Month { | ||
291 | self.set_mode(ViewMode::Day) | ||
292 | } else { | ||
293 | self.set_mode(ViewMode::Month) | ||
294 | } | ||
295 | return EventResult::Consumed(None); | ||
296 | } | ||
297 | Event::Char('V') => { | ||
298 | for habit in self.habits.iter_mut() { | ||
299 | habit.set_view_mode(ViewMode::Month); | ||
300 | } | ||
301 | return EventResult::Consumed(None); | ||
302 | } | ||
303 | Event::Key(Key::Esc) => { | ||
304 | for habit in self.habits.iter_mut() { | ||
305 | habit.set_view_mode(ViewMode::Day); | ||
306 | } | ||
307 | return EventResult::Consumed(None); | ||
308 | } | ||
286 | 309 | ||
287 | /* We want sifting to be an app level function, | 310 | /* We want sifting to be an app level function, |
288 | * that later trickles down into each habit | 311 | * that later trickles down into each habit |
diff --git a/src/views.rs b/src/views.rs index 3e623a9..f5ba01b 100644 --- a/src/views.rs +++ b/src/views.rs | |||
@@ -7,7 +7,7 @@ use cursive::{Printer, Vec2}; | |||
7 | use chrono::prelude::*; | 7 | use chrono::prelude::*; |
8 | use chrono::{Duration, Local, NaiveDate}; | 8 | use chrono::{Duration, Local, NaiveDate}; |
9 | 9 | ||
10 | use crate::habit::{Bit, Count, Habit, TrackEvent}; | 10 | use crate::habit::{Bit, Count, Habit, TrackEvent, ViewMode}; |
11 | 11 | ||
12 | use crate::CONFIGURATION; | 12 | use crate::CONFIGURATION; |
13 | 13 | ||
@@ -63,37 +63,64 @@ where | |||
63 | }, | 63 | }, |
64 | ); | 64 | ); |
65 | 65 | ||
66 | // fn draw_day(&self, p: &Printer) { }; | 66 | let draw_month = |printer: &Printer| { |
67 | // fn draw_month(&self, p: &Printer) {}; | 67 | let days = (1..31) |
68 | 68 | .map(|i| NaiveDate::from_ymd_opt(year, month, i)) | |
69 | // match self.view_mode() { | 69 | .flatten() // dates 28-31 may not exist, ignore them if they don't |
70 | // ViewMode::Day => draw_day(self, p), | 70 | .collect::<Vec<_>>(); |
71 | // ViewMode::Month => | 71 | for (week, line_nr) in days.chunks(7).zip(2..) { |
72 | // } | 72 | let weekly_goal = self.goal() * week.len() as u32; |
73 | 73 | let is_this_week = week.contains(&Local::now().naive_utc().date()); | |
74 | //let draw_day = |printer: &Printer| { | 74 | let remaining = week.iter().map(|&i| self.remaining(i)).sum::<u32>(); |
75 | let mut i = 1; | 75 | let completions = weekly_goal - remaining; |
76 | while let Some(d) = NaiveDate::from_ymd_opt(year, month, i) { | 76 | let full = CONFIGURATION.view_width - 8; |
77 | let day_style; | 77 | let bars_to_fill = (completions * full as u32) / weekly_goal; |
78 | if self.reached_goal(d) { | 78 | let percentage = (completions as f64 * 100f64) / weekly_goal as f64; |
79 | day_style = goal_reached_style; | ||
80 | } else { | ||
81 | day_style = todo_style; | ||
82 | } | ||
83 | let coords: Vec2 = ((i % 7) * 3, i / 7 + 2).into(); | ||
84 | if let Some(c) = self.get_by_date(d) { | ||
85 | printer.with_style(day_style, |p| { | ||
86 | p.print(coords, &format!("{:^3}", c)); | ||
87 | }); | ||
88 | } else { | ||
89 | printer.with_style(future_style, |p| { | 79 | printer.with_style(future_style, |p| { |
90 | p.print(coords, &format!("{:^3}", CONFIGURATION.future_chr)); | 80 | p.print((4, line_nr), &"―".repeat(full)); |
81 | }); | ||
82 | printer.with_style(goal_reached_style, |p| { | ||
83 | p.print((4, line_nr), &"―".repeat(bars_to_fill as usize)); | ||
91 | }); | 84 | }); |
85 | printer.with_style( | ||
86 | if is_this_week { | ||
87 | Style::none() | ||
88 | } else { | ||
89 | future_style | ||
90 | }, | ||
91 | |p| { | ||
92 | p.print((0, line_nr), &format!("{:3.0}% ", percentage)); | ||
93 | }, | ||
94 | ); | ||
92 | } | 95 | } |
93 | i += 1; | 96 | }; |
94 | } | 97 | let draw_day = |printer: &Printer| { |
95 | //}; | 98 | let mut i = 1; |
96 | //draw_day(printer); | 99 | while let Some(d) = NaiveDate::from_ymd_opt(year, month, i) { |
100 | let day_style; | ||
101 | if self.reached_goal(d) { | ||
102 | day_style = goal_reached_style; | ||
103 | } else { | ||
104 | day_style = todo_style; | ||
105 | } | ||
106 | let coords: Vec2 = ((i % 7) * 3, i / 7 + 2).into(); | ||
107 | if let Some(c) = self.get_by_date(d) { | ||
108 | printer.with_style(day_style, |p| { | ||
109 | p.print(coords, &format!("{:^3}", c)); | ||
110 | }); | ||
111 | } else { | ||
112 | printer.with_style(future_style, |p| { | ||
113 | p.print(coords, &format!("{:^3}", CONFIGURATION.future_chr)); | ||
114 | }); | ||
115 | } | ||
116 | i += 1; | ||
117 | } | ||
118 | }; | ||
119 | match self.view_mode() { | ||
120 | ViewMode::Day => draw_day(printer), | ||
121 | ViewMode::Month => draw_month(printer), | ||
122 | _ => draw_day(printer), | ||
123 | }; | ||
97 | } | 124 | } |
98 | 125 | ||
99 | fn required_size(&mut self, _: Vec2) -> Vec2 { | 126 | fn required_size(&mut self, _: Vec2) -> Vec2 { |