#include "pomodoro_timer.h" #include #include #include #include #include const NotificationSequence sequence_finish = { &message_display_backlight_on, &message_green_255, &message_vibro_on, &message_note_c5, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_e5, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_g5, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_b5, &message_delay_250, &message_vibro_off, &message_vibro_on, &message_note_c6, &message_delay_250, &message_vibro_off, &message_sound_off, NULL, }; const NotificationSequence sequence_rest = { &message_display_backlight_on, &message_red_255, &message_vibro_on, &message_note_c6, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_b5, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_g5, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_e5, &message_delay_100, &message_vibro_off, &message_vibro_on, &message_note_c5, &message_delay_250, &message_vibro_off, &message_sound_off, NULL, }; void pomodoro_timer_process(PomodoroTimer* pomodoro_timer, InputEvent* event) { with_view_model( pomodoro_timer->view, PomodoroTimerModel * model, { if(event->type == InputTypePress) { if(event->key == InputKeyOk) { model->ok_pressed = true; } else if(event->key == InputKeyLeft) { model->reset_pressed = true; } else if(event->key == InputKeyBack) { model->back_pressed = true; } } else if(event->type == InputTypeRelease) { if(event->key == InputKeyOk) { model->ok_pressed = false; // START/STOP TIMER FuriHalRtcDateTime curr_dt; furi_hal_rtc_get_datetime(&curr_dt); uint32_t current_timestamp = furi_hal_rtc_datetime_to_timestamp(&curr_dt); // STARTED -> PAUSED if(model->timer_running) { // Update stopped seconds model->timer_stopped_seconds = current_timestamp - model->timer_start_timestamp; } else if(!model->time_passed) { // INITIAL -> STARTED model->timer_start_timestamp = current_timestamp; model->rest_running = false; } else { // PAUSED -> STARTED model->timer_start_timestamp = current_timestamp - model->timer_stopped_seconds; } model->timer_running = !model->timer_running; } else if(event->key == InputKeyLeft) { if(!model->timer_running) { furi_record_close(RECORD_NOTIFICATION); model->timer_stopped_seconds = 0; model->timer_start_timestamp = 0; model->time_passed = 0; model->timer_running = false; } model->reset_pressed = false; } else if(event->key == InputKeyBack) { model->back_pressed = false; } } }, true); } void pomodoro_draw_callback(Canvas* canvas, void* context, int max_seconds, int max_seconds_rest) { furi_assert(context); PomodoroTimerModel* model = context; FuriHalRtcDateTime curr_dt; furi_hal_rtc_get_datetime(&curr_dt); uint32_t current_timestamp = furi_hal_rtc_datetime_to_timestamp(&curr_dt); // Header canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Pomodoro"); canvas_draw_icon(canvas, 68, 1, &I_Pin_back_arrow_10x8); canvas_set_font(canvas, FontSecondary); elements_multiline_text_aligned(canvas, 127, 1, AlignRight, AlignTop, "Hold to exit"); // Start/Pause/Continue int txt_main_y = 34; canvas_draw_icon(canvas, 63, 23, &I_Space_65x18); // button if(model->ok_pressed) { elements_slightly_rounded_box(canvas, 66, 25, 60, 13); canvas_set_color(canvas, ColorWhite); } if(model->timer_running) { model->time_passed = current_timestamp - model->timer_start_timestamp; elements_multiline_text_aligned(canvas, 83, txt_main_y, AlignLeft, AlignBottom, "Pause"); canvas_draw_box(canvas, 71, 27, 2, 8); canvas_draw_box(canvas, 75, 27, 2, 8); } else { if(model->time_passed) { elements_multiline_text_aligned( canvas, 83, txt_main_y, AlignLeft, AlignBottom, "Continue"); } else { elements_multiline_text_aligned( canvas, 83, txt_main_y, AlignLeft, AlignBottom, "Start"); } canvas_draw_icon(canvas, 70, 26, &I_Ok_btn_9x9); // OK icon } canvas_set_color(canvas, ColorBlack); // Reset if(!model->timer_running && model->time_passed) { canvas_draw_icon(canvas, 63, 46, &I_Space_65x18); if(model->reset_pressed) { elements_slightly_rounded_box(canvas, 66, 48, 60, 13); canvas_set_color(canvas, ColorWhite); } canvas_draw_icon(canvas, 72, 50, &I_ButtonLeft_4x7); elements_multiline_text_aligned(canvas, 83, 57, AlignLeft, AlignBottom, "Reset"); canvas_set_color(canvas, ColorBlack); } char buffer[64]; // Time to work int total_time_left = (max_seconds - (uint32_t)model->time_passed); int minutes_left = total_time_left / 60; int seconds_left = total_time_left % 60; canvas_set_font(canvas, FontBigNumbers); // Play sound if(total_time_left == 0 && !model->sound_playing) { model->sound_playing = true; notification_message(furi_record_open(RECORD_NOTIFICATION), &sequence_finish); } if(total_time_left < 0) { model->timer_running = false; model->time_passed = 0; model->sound_playing = false; model->rest_running = true; model->rest_start_timestamp = current_timestamp; seconds_left = 0; model->counter += 1; } if(!model->rest_running) { snprintf(buffer, sizeof(buffer), "%02d:%02d", minutes_left, seconds_left); canvas_draw_str(canvas, 0, 39, buffer); } if(model->timer_running) { canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 0, 50, AlignLeft, AlignTop, "Time to work"); } // Time to rest if(model->rest_running && !model->timer_running) { canvas_set_font(canvas, FontBigNumbers); int rest_passed = current_timestamp - model->rest_start_timestamp; int rest_total_time_left = (max_seconds_rest - rest_passed); int rest_minutes_left = rest_total_time_left / 60; int rest_seconds_left = rest_total_time_left % 60; // Play sound if(rest_total_time_left == 0 && !model->sound_playing) { model->sound_playing = true; notification_message(furi_record_open(RECORD_NOTIFICATION), &sequence_rest); } if(rest_total_time_left < 0) { rest_seconds_left = 0; model->rest_running = false; model->sound_playing = false; } snprintf(buffer, sizeof(buffer), "%02d:%02d", rest_minutes_left, rest_seconds_left); canvas_draw_str(canvas, 0, 60, buffer); canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 0, 27, AlignLeft, AlignTop, "Have a rest"); } // Clocks canvas_set_font(canvas, FontSecondary); snprintf( buffer, sizeof(buffer), "%02ld:%02ld:%02ld", ((uint32_t)current_timestamp % (60 * 60 * 24)) / (60 * 60), ((uint32_t)current_timestamp % (60 * 60)) / 60, (uint32_t)current_timestamp % 60); canvas_draw_str(canvas, 0, 20, buffer); // Tomato counter if(model->counter > 5) { model->counter = 1; } for(int i = 0; i < model->counter; ++i) { canvas_draw_disc(canvas, 122 - i * 10, 15, 4); } }