Skip to content

Commit 0a1b42c

Browse files
committed
API 31 / unzip sources
0 parents  commit 0a1b42c

26 files changed

+776
-0
lines changed

application.fam

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
App(
2+
appid="flipp_pomodoro",
3+
name="Flipp Pomodoro",
4+
apptype=FlipperAppType.EXTERNAL,
5+
entry_point="flipp_pomodoro_app",
6+
requires=["gui", "notification", "dolphin"],
7+
stack_size=1 * 1024,
8+
fap_category="Misc_Extra",
9+
fap_icon_assets="images",
10+
fap_icon="flipp_pomodoro_10.png",
11+
)

flipp_pomodoro_10.png

157 Bytes
Loading

flipp_pomodoro_app.c

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include "flipp_pomodoro_app_i.h"
2+
3+
enum {
4+
CustomEventConsumed = true,
5+
CustomEventNotConsumed = false,
6+
};
7+
8+
static bool flipp_pomodoro_app_back_event_callback(void* ctx) {
9+
furi_assert(ctx);
10+
FlippPomodoroApp* app = ctx;
11+
return scene_manager_handle_back_event(app->scene_manager);
12+
};
13+
14+
static void flipp_pomodoro_app_tick_event_callback(void* ctx) {
15+
furi_assert(ctx);
16+
FlippPomodoroApp* app = ctx;
17+
18+
scene_manager_handle_custom_event(app->scene_manager, FlippPomodoroAppCustomEventTimerTick);
19+
};
20+
21+
static bool flipp_pomodoro_app_custom_event_callback(void* ctx, uint32_t event) {
22+
furi_assert(ctx);
23+
FlippPomodoroApp* app = ctx;
24+
25+
switch(event) {
26+
case FlippPomodoroAppCustomEventStageSkip:
27+
flipp_pomodoro__toggle_stage(app->state);
28+
view_dispatcher_send_custom_event(
29+
app->view_dispatcher, FlippPomodoroAppCustomEventStateUpdated);
30+
return CustomEventConsumed;
31+
case FlippPomodoroAppCustomEventStageComplete:
32+
if(flipp_pomodoro__get_stage(app->state) == FlippPomodoroStageFocus) {
33+
// REGISTER a deed on work stage complete to get an acheivement
34+
dolphin_deed(DolphinDeedPluginGameWin);
35+
};
36+
37+
flipp_pomodoro__toggle_stage(app->state);
38+
notification_message(
39+
app->notification_app,
40+
stage_start_notification_sequence_map[flipp_pomodoro__get_stage(app->state)]);
41+
view_dispatcher_send_custom_event(
42+
app->view_dispatcher, FlippPomodoroAppCustomEventStateUpdated);
43+
return CustomEventConsumed;
44+
default:
45+
break;
46+
}
47+
return scene_manager_handle_custom_event(app->scene_manager, event);
48+
};
49+
50+
FlippPomodoroApp* flipp_pomodoro_app_alloc() {
51+
FlippPomodoroApp* app = malloc(sizeof(FlippPomodoroApp));
52+
app->state = flipp_pomodoro__new();
53+
54+
app->scene_manager = scene_manager_alloc(&flipp_pomodoro_scene_handlers, app);
55+
app->gui = furi_record_open(RECORD_GUI);
56+
app->notification_app = furi_record_open(RECORD_NOTIFICATION);
57+
58+
app->view_dispatcher = view_dispatcher_alloc();
59+
view_dispatcher_enable_queue(app->view_dispatcher);
60+
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
61+
view_dispatcher_set_custom_event_callback(
62+
app->view_dispatcher, flipp_pomodoro_app_custom_event_callback);
63+
view_dispatcher_set_tick_event_callback(
64+
app->view_dispatcher, flipp_pomodoro_app_tick_event_callback, 1000);
65+
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
66+
view_dispatcher_set_navigation_event_callback(
67+
app->view_dispatcher, flipp_pomodoro_app_back_event_callback);
68+
69+
app->timer_view = flipp_pomodoro_view_timer_alloc();
70+
71+
view_dispatcher_add_view(
72+
app->view_dispatcher,
73+
FlippPomodoroAppViewTimer,
74+
flipp_pomodoro_view_timer_get_view(app->timer_view));
75+
76+
scene_manager_next_scene(app->scene_manager, FlippPomodoroSceneTimer);
77+
78+
return app;
79+
};
80+
81+
void flipp_pomodoro_app_free(FlippPomodoroApp* app) {
82+
view_dispatcher_remove_view(app->view_dispatcher, FlippPomodoroAppViewTimer);
83+
view_dispatcher_free(app->view_dispatcher);
84+
scene_manager_free(app->scene_manager);
85+
flipp_pomodoro_view_timer_free(app->timer_view);
86+
free(app);
87+
furi_record_close(RECORD_GUI);
88+
furi_record_close(RECORD_NOTIFICATION);
89+
};
90+
91+
int32_t flipp_pomodoro_app(void* p) {
92+
UNUSED(p);
93+
FlippPomodoroApp* app = flipp_pomodoro_app_alloc();
94+
95+
view_dispatcher_run(app->view_dispatcher);
96+
97+
flipp_pomodoro_app_free(app);
98+
99+
return 0;
100+
};

flipp_pomodoro_app.h

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include <furi.h>
4+
#include <furi_hal.h>
5+
#include <gui/gui.h>
6+
#include <gui/view_dispatcher.h>
7+
#include <gui/scene_manager.h>
8+
#include <notification/notification_messages.h>
9+
#include "views/flipp_pomodoro_timer_view.h"
10+
11+
#include "modules/flipp_pomodoro.h"
12+
13+
typedef enum {
14+
// Reserve first 100 events for button types and indexes, starting from 0
15+
FlippPomodoroAppCustomEventStageSkip = 100,
16+
FlippPomodoroAppCustomEventStageComplete, // By Expiration
17+
FlippPomodoroAppCustomEventTimerTick,
18+
FlippPomodoroAppCustomEventStateUpdated,
19+
} FlippPomodoroAppCustomEvent;
20+
21+
typedef struct {
22+
SceneManager* scene_manager;
23+
ViewDispatcher* view_dispatcher;
24+
Gui* gui;
25+
NotificationApp* notification_app;
26+
FlippPomodoroTimerView* timer_view;
27+
FlippPomodoroState* state;
28+
} FlippPomodoroApp;
29+
30+
typedef enum {
31+
FlippPomodoroAppViewTimer,
32+
} FlippPomodoroAppView;

flipp_pomodoro_app_i.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#define FURI_DEBUG 1
4+
5+
/**
6+
* Index of dependencies for the main app
7+
*/
8+
9+
// Platform Imports
10+
11+
#include <furi.h>
12+
#include <furi_hal.h>
13+
#include <gui/gui.h>
14+
#include <gui/view_stack.h>
15+
#include <gui/view_dispatcher.h>
16+
#include <gui/scene_manager.h>
17+
#include <gui/elements.h>
18+
#include <dolphin/dolphin.h>
19+
#include <input/input.h>
20+
21+
// App resource imports
22+
23+
#include "helpers/time.h"
24+
#include "helpers/notifications.h"
25+
#include "modules/flipp_pomodoro.h"
26+
#include "flipp_pomodoro_app.h"
27+
#include "scenes/flipp_pomodoro_scene.h"
28+
#include "views/flipp_pomodoro_timer_view.h"
29+
30+
// Auto-compiled icons
31+
#include "flipp_pomodoro_icons.h"

helpers/debug.h

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#include <furi.h>
4+
5+
#define TAG "FlippPomodoro"

helpers/notifications.c

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <notification/notification_messages.h>
2+
3+
const NotificationSequence work_start_notification = {
4+
&message_display_backlight_on,
5+
6+
&message_vibro_on,
7+
8+
&message_note_b5,
9+
&message_delay_250,
10+
11+
&message_note_d5,
12+
&message_delay_250,
13+
14+
&message_sound_off,
15+
&message_vibro_off,
16+
17+
&message_green_255,
18+
&message_delay_1000,
19+
&message_green_0,
20+
&message_delay_250,
21+
&message_green_255,
22+
&message_delay_1000,
23+
24+
NULL,
25+
};
26+
27+
const NotificationSequence rest_start_notification = {
28+
&message_display_backlight_on,
29+
30+
&message_vibro_on,
31+
32+
&message_note_d5,
33+
&message_delay_250,
34+
35+
&message_note_b5,
36+
&message_delay_250,
37+
38+
&message_sound_off,
39+
&message_vibro_off,
40+
41+
&message_red_255,
42+
&message_delay_1000,
43+
&message_red_0,
44+
&message_delay_250,
45+
&message_red_255,
46+
&message_delay_1000,
47+
48+
NULL,
49+
};

helpers/notifications.h

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
3+
#include "../modules/flipp_pomodoro.h"
4+
#include <notification/notification_messages.h>
5+
6+
extern const NotificationSequence work_start_notification;
7+
extern const NotificationSequence rest_start_notification;
8+
9+
/// @brief Defines a notification sequence that should indicate start of specific pomodoro stage.
10+
const NotificationSequence* stage_start_notification_sequence_map[] = {
11+
[FlippPomodoroStageFocus] = &work_start_notification,
12+
[FlippPomodoroStageRest] = &rest_start_notification,
13+
[FlippPomodoroStageLongBreak] = &rest_start_notification,
14+
};

helpers/time.c

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <furi.h>
2+
#include <furi_hal.h>
3+
#include "time.h"
4+
5+
const int TIME_SECONDS_IN_MINUTE = 60;
6+
const int TIME_MINUTES_IN_HOUR = 60;
7+
8+
uint32_t time_now() {
9+
return furi_hal_rtc_get_timestamp();
10+
};
11+
12+
TimeDifference time_difference_seconds(uint32_t begin, uint32_t end) {
13+
const uint32_t duration_seconds = end - begin;
14+
15+
uint32_t minutes = (duration_seconds / TIME_MINUTES_IN_HOUR) % TIME_MINUTES_IN_HOUR;
16+
uint32_t seconds = duration_seconds % TIME_SECONDS_IN_MINUTE;
17+
18+
return (
19+
TimeDifference){.total_seconds = duration_seconds, .minutes = minutes, .seconds = seconds};
20+
};

helpers/time.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <furi.h>
4+
#include <furi_hal.h>
5+
6+
extern const int TIME_SECONDS_IN_MINUTE;
7+
extern const int TIME_MINUTES_IN_HOUR;
8+
9+
/// @brief Container for a time period
10+
typedef struct {
11+
uint8_t seconds;
12+
uint8_t minutes;
13+
uint32_t total_seconds;
14+
} TimeDifference;
15+
16+
/// @brief Time by the moment of calling
17+
/// @return A timestamp(seconds percision)
18+
uint32_t time_now();
19+
20+
/// @brief Calculates difference between two provided timestamps
21+
/// @param begin - start timestamp of the period
22+
/// @param end - end timestamp of the period to measure
23+
/// @return TimeDifference struct
24+
TimeDifference time_difference_seconds(uint32_t begin, uint32_t end);
1.21 KB
Loading
1.19 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1
1.06 KB
Loading
1.05 KB
Loading
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

modules/flipp_pomodoro.c

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include <furi.h>
2+
#include <furi_hal.h>
3+
#include "../helpers/time.h"
4+
#include "flipp_pomodoro.h"
5+
6+
PomodoroStage stages_sequence[] = {
7+
FlippPomodoroStageFocus,
8+
FlippPomodoroStageRest,
9+
10+
FlippPomodoroStageFocus,
11+
FlippPomodoroStageRest,
12+
13+
FlippPomodoroStageFocus,
14+
FlippPomodoroStageRest,
15+
16+
FlippPomodoroStageFocus,
17+
FlippPomodoroStageLongBreak,
18+
};
19+
20+
char* current_stage_label[] = {
21+
[FlippPomodoroStageFocus] = "Continue focus for:",
22+
[FlippPomodoroStageRest] = "Keep rest for:",
23+
[FlippPomodoroStageLongBreak] = "Long Break for:",
24+
};
25+
26+
char* next_stage_label[] = {
27+
[FlippPomodoroStageFocus] = "Focus",
28+
[FlippPomodoroStageRest] = "Short Break",
29+
[FlippPomodoroStageLongBreak] = "Long Break",
30+
};
31+
32+
PomodoroStage flipp_pomodoro__stage_by_index(int index) {
33+
const int one_loop_size = sizeof(stages_sequence);
34+
return stages_sequence[index % one_loop_size];
35+
}
36+
37+
void flipp_pomodoro__toggle_stage(FlippPomodoroState* state) {
38+
furi_assert(state);
39+
state->current_stage_index = state->current_stage_index + 1;
40+
state->started_at_timestamp = time_now();
41+
};
42+
43+
PomodoroStage flipp_pomodoro__get_stage(FlippPomodoroState* state) {
44+
furi_assert(state);
45+
return flipp_pomodoro__stage_by_index(state->current_stage_index);
46+
};
47+
48+
char* flipp_pomodoro__current_stage_label(FlippPomodoroState* state) {
49+
furi_assert(state);
50+
return current_stage_label[flipp_pomodoro__get_stage(state)];
51+
};
52+
53+
char* flipp_pomodoro__next_stage_label(FlippPomodoroState* state) {
54+
furi_assert(state);
55+
return next_stage_label[flipp_pomodoro__stage_by_index(state->current_stage_index + 1)];
56+
};
57+
58+
uint32_t flipp_pomodoro__current_stage_total_duration(FlippPomodoroState* state) {
59+
const int32_t stage_duration_seconds_map[] = {
60+
[FlippPomodoroStageFocus] = 25 * TIME_SECONDS_IN_MINUTE,
61+
[FlippPomodoroStageRest] = 5 * TIME_SECONDS_IN_MINUTE,
62+
[FlippPomodoroStageLongBreak] = 30 * TIME_SECONDS_IN_MINUTE,
63+
};
64+
65+
return stage_duration_seconds_map[flipp_pomodoro__get_stage(state)];
66+
};
67+
68+
uint32_t flipp_pomodoro__stage_expires_timestamp(FlippPomodoroState* state) {
69+
return state->started_at_timestamp + flipp_pomodoro__current_stage_total_duration(state);
70+
};
71+
72+
TimeDifference flipp_pomodoro__stage_remaining_duration(FlippPomodoroState* state) {
73+
const uint32_t stage_ends_at = flipp_pomodoro__stage_expires_timestamp(state);
74+
return time_difference_seconds(time_now(), stage_ends_at);
75+
};
76+
77+
bool flipp_pomodoro__is_stage_expired(FlippPomodoroState* state) {
78+
const uint32_t expired_by = flipp_pomodoro__stage_expires_timestamp(state);
79+
const uint8_t seamless_change_span_seconds = 1;
80+
return (time_now() - seamless_change_span_seconds) >= expired_by;
81+
};
82+
83+
FlippPomodoroState* flipp_pomodoro__new() {
84+
FlippPomodoroState* state = malloc(sizeof(FlippPomodoroState));
85+
const uint32_t now = time_now();
86+
state->started_at_timestamp = now;
87+
state->current_stage_index = 0;
88+
return state;
89+
};

0 commit comments

Comments
 (0)