Skip to content

Commit 8f7000a

Browse files
committed
Give alarms and timers optional names.
Signed-off-by: Katharine Berry <ktbry@google.com>
1 parent a6b6441 commit 8f7000a

File tree

17 files changed

+239
-94
lines changed

17 files changed

+239
-94
lines changed

app/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@
7474
"REMINDER_ID",
7575
"REMINDER_TIME",
7676
"REMINDER_DELETE",
77-
"ACTION_REMINDER_DELETED"
77+
"ACTION_REMINDER_DELETED",
78+
"SET_ALARM_NAME",
79+
"GET_ALARM_NAME[9]"
7880
],
7981
"resources": {
8082
"media": [

app/src/c/alarms/alarm_window.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
typedef struct {
2828
time_t time;
2929
bool is_timer;
30+
char *name;
3031
TextLayer *title_layer;
3132
TextLayer *time_layer;
3233
StatusBarLayer *status_bar;
@@ -52,12 +53,18 @@ static void prv_click_config_provider(void *context);
5253
static void prv_handle_snooze(ClickRecognizerRef recognizer, void *context);
5354
static void prv_handle_dismiss(ClickRecognizerRef recognizer, void *context);
5455

55-
void alarm_window_push(time_t alarm_time, bool is_timer) {
56+
void alarm_window_push(time_t alarm_time, bool is_timer, char *name) {
5657
Window* window = window_create();
5758
AlarmWindowData *data = malloc(sizeof(AlarmWindowData));
5859
data->time = alarm_time;
5960
data->is_timer = is_timer;
6061
data->timer = NULL;
62+
data->name = NULL;
63+
if (name) {
64+
size_t len = strlen(name);
65+
data->name = malloc(len + 1);
66+
strncpy(data->name, name, len + 1);
67+
}
6168
window_set_user_data(window, data);
6269
window_set_window_handlers(window, (WindowHandlers) {
6370
.load = prv_window_load,
@@ -72,13 +79,19 @@ static void prv_window_load(Window *window) {
7279
AlarmWindowData* data = window_get_user_data(window);
7380
Layer* root_layer = window_get_root_layer(window);
7481
GRect rect = layer_get_bounds(root_layer);
75-
data->title_layer = text_layer_create(GRect(0, STATUS_BAR_LAYER_HEIGHT, rect.size.w - ACTION_BAR_WIDTH, 35));
76-
text_layer_set_text(data->title_layer, data->is_timer ? "Time's up!" : "Alarm!");
82+
data->title_layer = text_layer_create(GRect(0, STATUS_BAR_LAYER_HEIGHT, rect.size.w - ACTION_BAR_WIDTH, 70));
83+
if (data->name) {
84+
text_layer_set_text(data->title_layer, data->name);
85+
} else {
86+
text_layer_set_text(data->title_layer, data->is_timer ? "Time's up!" : "Alarm!");
87+
}
7788
text_layer_set_font(data->title_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
7889
text_layer_set_text_alignment(data->title_layer, GTextAlignmentCenter);
7990
text_layer_set_background_color(data->title_layer, GColorClear);
8091
layer_add_child(root_layer, (Layer *)data->title_layer);
81-
data->time_layer = text_layer_create(GRect(0, STATUS_BAR_LAYER_HEIGHT + 35 + 15, rect.size.w - ACTION_BAR_WIDTH, 45));
92+
GSize title_size = text_layer_get_content_size(data->title_layer);
93+
int16_t remaining_height = rect.size.h - STATUS_BAR_LAYER_HEIGHT - title_size.h - 49;
94+
data->time_layer = text_layer_create(GRect(0, STATUS_BAR_LAYER_HEIGHT + title_size.h + remaining_height / 2 - 22 / 2, rect.size.w - ACTION_BAR_WIDTH, 32));
8295
text_layer_set_font(data->time_layer, fonts_get_system_font(FONT_KEY_LECO_32_BOLD_NUMBERS));
8396
text_layer_set_text_alignment(data->time_layer, GTextAlignmentCenter);
8497
text_layer_set_background_color(data->time_layer, GColorClear);
@@ -122,6 +135,9 @@ static void prv_window_unload(Window *window) {
122135
gdraw_command_sequence_destroy(data->draw_commands);
123136
vector_sequence_layer_destroy(data->animation_layer);
124137
events_tick_timer_service_unsubscribe(data->tick_handle);
138+
if (data->name) {
139+
free(data->name);
140+
}
125141
free(data);
126142
window_destroy(window);
127143
}
@@ -206,9 +222,9 @@ static void prv_handle_snooze(ClickRecognizerRef recognizer, void *context) {
206222
AlarmWindowData* data = window_get_user_data(window);
207223
int result;
208224
if (data->is_timer) {
209-
result = alarm_manager_add_alarm(time(NULL) + 60, true,false);
225+
result = alarm_manager_add_alarm(time(NULL) + 60, true, data->name, false);
210226
} else {
211-
result = alarm_manager_add_alarm(time(NULL) + 600, false,false);
227+
result = alarm_manager_add_alarm(time(NULL) + 600, false, data->name, false);
212228
}
213229
if (result == S_SUCCESS) {
214230
const char* text = data->is_timer ? "Snoozed for 1 minute" : "Snoozed for 10 minutes";

app/src/c/alarms/alarm_window.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@
1919

2020
#include <pebble.h>
2121

22-
void alarm_window_push(time_t alarm_time, bool is_timer);
22+
void alarm_window_push(time_t alarm_time, bool is_timer, char *name);
2323

2424
#endif

app/src/c/alarms/manager.c

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
struct Alarm {
2727
time_t scheduled_time;
2828
WakeupId wakeup_id;
29+
char *name;
2930
bool is_timer; // what's the difference between an alarm and a timer? the user's intention.
3031
};
3132

@@ -44,8 +45,8 @@ static void prv_handle_app_message_inbox_received(DictionaryIterator *iterator,
4445
static void prv_send_alarm_response(StatusCode response);
4546
static void prv_wakeup_handler(WakeupId wakeup_id, int32_t cookie);
4647

47-
4848
#define MAX_ALARMS 8
49+
#define ALARM_NAME_SIZE 32
4950

5051
void alarm_manager_init() {
5152
wakeup_service_subscribe(prv_wakeup_handler);
@@ -55,7 +56,7 @@ void alarm_manager_init() {
5556
prv_load_alarms();
5657
}
5758

58-
int alarm_manager_add_alarm(time_t when, bool is_timer, bool conversational) {
59+
int alarm_manager_add_alarm(time_t when, bool is_timer, char* name, bool conversational) {
5960
if (s_manager.pending_alarm_count >= MAX_ALARMS) {
6061
APP_LOG(APP_LOG_LEVEL_WARNING, "Not scheduling alarm because MAX_ALARMS (%d) was already reached.", MAX_ALARMS);
6162
return E_OUT_OF_RESOURCES;
@@ -82,6 +83,15 @@ int alarm_manager_add_alarm(time_t when, bool is_timer, bool conversational) {
8283
alarm->scheduled_time = when;
8384
alarm->is_timer = is_timer;
8485
alarm->wakeup_id = id;
86+
alarm->name = NULL;
87+
size_t name_len = 0;
88+
if (name) {
89+
name_len = strlen(name);
90+
if (name_len > 0) {
91+
alarm->name = malloc(name_len + 1);
92+
strncpy(alarm->name, name, name_len + 1);
93+
}
94+
}
8595

8696
if (conversational && conversation_manager_get_current()) {
8797
ConversationManager *conversation_manager = conversation_manager_get_current();
@@ -92,9 +102,16 @@ int alarm_manager_add_alarm(time_t when, bool is_timer, bool conversational) {
92102
.time = alarm->scheduled_time,
93103
.is_timer = alarm->is_timer,
94104
.deleted = false,
105+
.name = NULL,
95106
}
96107
}
97108
};
109+
// The alarm manager and conversation manager both expect to own the alarm name, so it has to be copied to both
110+
// places here.
111+
if (name) {
112+
action.action.set_alarm.name = malloc(name_len + 1);
113+
strncpy(action.action.set_alarm.name, name, name_len + 1);
114+
}
98115
conversation_manager_add_action(conversation_manager, &action);
99116
}
100117

@@ -144,10 +161,12 @@ static void prv_load_alarms() {
144161
time_t times[MAX_ALARMS];
145162
WakeupId wakeup_ids[MAX_ALARMS];
146163
bool is_timers[MAX_ALARMS];
164+
char names[MAX_ALARMS][ALARM_NAME_SIZE];
147165

148166
persist_read_data(PERSIST_KEY_ALARM_TIMES, &times, sizeof(times));
149167
persist_read_data(PERSIST_KEY_ALARM_WAKEUP_IDS, &wakeup_ids, sizeof(wakeup_ids));
150168
persist_read_data(PERSIST_KEY_ALARM_IS_TIMERS, &is_timers, sizeof(is_timers));
169+
persist_read_data(PERSIST_KEY_ALARM_NAMES, &names, sizeof(names));
151170

152171
s_manager.pending_alarms = malloc(sizeof(Alarm) * alarm_count);
153172
s_manager.pending_alarm_count = alarm_count;
@@ -169,11 +188,21 @@ static void prv_load_alarms() {
169188
alarm->scheduled_time = times[i];
170189
alarm->wakeup_id = wakeup_ids[i];
171190
alarm->is_timer = is_timers[i];
191+
size_t name_len = strlen(names[i]);
192+
if (name_len >= ALARM_NAME_SIZE) {
193+
name_len = ALARM_NAME_SIZE - 1;
194+
}
195+
if (name_len == 0) {
196+
alarm->name = NULL;
197+
} else {
198+
alarm->name = malloc(name_len + 1);
199+
strncpy(alarm->name, names[i], name_len + 1);
200+
}
172201
}
173202
s_manager.pending_alarm_count = j;
174203

175204
if (did_drop_entries) {
176-
APP_LOG(APP_LOG_LEVEL_INFO, "Updating saved data after droping entries.");
205+
APP_LOG(APP_LOG_LEVEL_INFO, "Updating saved data after dropping entries.");
177206
prv_save_alarms();
178207
}
179208
}
@@ -185,23 +214,33 @@ static void prv_save_alarms() {
185214
persist_delete(PERSIST_KEY_ALARM_TIMES);
186215
persist_delete(PERSIST_KEY_ALARM_WAKEUP_IDS);
187216
persist_delete(PERSIST_KEY_ALARM_IS_TIMERS);
217+
persist_delete(PERSIST_KEY_ALARM_NAMES);
188218
persist_delete(PERSIST_KEY_ALARM_COUNT_TWO);
189219
wakeup_cancel_all();
190220
}
191221
time_t times[MAX_ALARMS];
192222
WakeupId wakeup_ids[MAX_ALARMS];
193223
bool is_timers[MAX_ALARMS];
224+
char names[MAX_ALARMS][ALARM_NAME_SIZE];
225+
memset(names, 0, sizeof(names));
194226
for (int i = 0; i < s_manager.pending_alarm_count; ++i) {
195227
Alarm* alarm = &s_manager.pending_alarms[i];
196228
times[i] = alarm->scheduled_time;
197229
wakeup_ids[i] = alarm->wakeup_id;
198230
is_timers[i] = alarm->is_timer;
231+
if (alarm->name) {
232+
strncpy(names[i], alarm->name, ALARM_NAME_SIZE);
233+
names[i][ALARM_NAME_SIZE - 1] = '\0';
234+
} else {
235+
names[i][0] = '\0';
236+
}
199237
}
200238

201239
persist_write_int(PERSIST_KEY_ALARM_COUNT_ONE, s_manager.pending_alarm_count);
202240
persist_write_data(PERSIST_KEY_ALARM_TIMES, &times, sizeof(times));
203241
persist_write_data(PERSIST_KEY_ALARM_WAKEUP_IDS, &wakeup_ids, sizeof(wakeup_ids));
204242
persist_write_data(PERSIST_KEY_ALARM_IS_TIMERS, &is_timers, sizeof(is_timers));
243+
persist_write_data(PERSIST_KEY_ALARM_NAMES, &names, sizeof(names));
205244
persist_write_int(PERSIST_KEY_ALARM_COUNT_TWO, s_manager.pending_alarm_count);
206245
APP_LOG(APP_LOG_LEVEL_INFO, "Wrote %d alarms.", s_manager.pending_alarm_count);
207246
}
@@ -221,12 +260,22 @@ static void prv_remove_alarm(int to_remove) {
221260
.time = alarm->scheduled_time,
222261
.is_timer = alarm->is_timer,
223262
.deleted = true,
263+
.name = NULL,
224264
}
225265
}
226266
};
267+
if (alarm->name) {
268+
size_t name_len = strlen(alarm->name);
269+
action.action.set_alarm.name = malloc(name_len + 1);
270+
strncpy(action.action.set_alarm.name, alarm->name, name_len + 1);
271+
}
227272
conversation_manager_add_action(conversation_manager, &action);
228273
}
229274

275+
if (alarm->name) {
276+
free(alarm->name);
277+
}
278+
230279
if (s_manager.pending_alarm_count == 1) {
231280
free(s_manager.pending_alarms);
232281
s_manager.pending_alarms = NULL;
@@ -263,7 +312,7 @@ bool alarm_manager_maybe_alarm() {
263312
APP_LOG(APP_LOG_LEVEL_INFO, "comparing %d == %d", alarm->wakeup_id, id);
264313
if (alarm->wakeup_id == id) {
265314
APP_LOG(APP_LOG_LEVEL_INFO, "alarm found! alarming...");
266-
alarm_window_push(alarm->scheduled_time, alarm->is_timer);
315+
alarm_window_push(alarm->scheduled_time, alarm->is_timer, alarm->name);
267316
prv_remove_alarm(i);
268317
return true;
269318
}
@@ -279,6 +328,10 @@ bool alarm_is_timer(Alarm* alarm) {
279328
return alarm->is_timer;
280329
}
281330

331+
char* alarm_get_name(Alarm* alarm) {
332+
return alarm->name;
333+
}
334+
282335
static void prv_handle_set_alarm_request(DictionaryIterator *iterator, void *context) {
283336
Tuple* tuple = dict_find(iterator, MESSAGE_KEY_SET_ALARM_TIME);
284337
if (tuple == NULL) {
@@ -294,7 +347,12 @@ static void prv_handle_set_alarm_request(DictionaryIterator *iterator, void *con
294347
if (is_timer) {
295348
alarm_time += time(NULL);
296349
}
297-
StatusCode result = alarm_manager_add_alarm(alarm_time, is_timer,true);
350+
tuple = dict_find(iterator, MESSAGE_KEY_SET_ALARM_NAME);
351+
char* name = NULL;
352+
if (tuple != NULL && strlen(tuple->value->cstring) > 0) {
353+
name = tuple->value->cstring;
354+
}
355+
StatusCode result = alarm_manager_add_alarm(alarm_time, is_timer, name, true);
298356
prv_send_alarm_response(result);
299357
if (result == S_SUCCESS) {
300358
APP_LOG(APP_LOG_LEVEL_INFO, "Set alarm for %d (is timer: %d)", alarm_time, is_timer);
@@ -315,7 +373,9 @@ static void prv_handle_get_alarm_request(int16_t is_timer, void* context) {
315373
for (int i = 0; i < s_manager.pending_alarm_count; ++i) {
316374
Alarm* alarm = &s_manager.pending_alarms[i];
317375
if (alarm->is_timer == is_timer) {
318-
dict_write_int32(iter, MESSAGE_KEY_GET_ALARM_RESULT + ++write_index, alarm->scheduled_time);
376+
++write_index;
377+
dict_write_int32(iter, MESSAGE_KEY_GET_ALARM_RESULT + write_index, alarm->scheduled_time);
378+
dict_write_cstring(iter, MESSAGE_KEY_GET_ALARM_NAME + write_index, alarm->name);
319379
}
320380
}
321381
dict_write_int16(iter, MESSAGE_KEY_GET_ALARM_RESULT, write_index);
@@ -394,7 +454,7 @@ static void prv_wakeup_handler(WakeupId wakeup_id, int32_t cookie) {
394454
APP_LOG(APP_LOG_LEVEL_INFO, "comparing %d == %d", alarm->wakeup_id, wakeup_id);
395455
if (alarm->wakeup_id == wakeup_id) {
396456
APP_LOG(APP_LOG_LEVEL_INFO, "alarm found! alarming...");
397-
alarm_window_push(alarm->scheduled_time, alarm->is_timer);
457+
alarm_window_push(alarm->scheduled_time, alarm->is_timer, alarm->name);
398458
prv_remove_alarm(i);
399459
break;
400460
}

app/src/c/alarms/manager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ typedef struct AlarmManager AlarmManager;
2323
typedef struct Alarm Alarm;
2424

2525
void alarm_manager_init();
26-
int alarm_manager_add_alarm(time_t when, bool is_timer, bool conversational);
26+
int alarm_manager_add_alarm(time_t when, bool is_timer, char* name, bool conversational);
2727
int alarm_manager_cancel_alarm(time_t when, bool is_timer);
2828
int alarm_manager_get_alarm_count();
2929
Alarm* alarm_manager_get_alarm(int index);
3030
bool alarm_manager_maybe_alarm();
3131

3232
time_t alarm_get_time(Alarm* alarm);
3333
bool alarm_is_timer(Alarm* alarm);
34+
char* alarm_get_name(Alarm* alarm);
3435

3536
#endif

app/src/c/converse/conversation.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,21 @@ void conversation_destroy(Conversation* conversation) {
6868
free(entry->content.error);
6969
break;
7070
case EntryTypeAction:
71-
// Only generic sentence actions need further cleanup.
72-
if (entry->content.action->type == ConversationActionTypeGenericSentence) {
73-
free(entry->content.action->action.generic_sentence.sentence);
71+
// Only alarms and generic sentence actions need further cleanup.
72+
switch (entry->content.action->type) {
73+
case ConversationActionTypeSetAlarm:
74+
if (entry->content.action->action.set_alarm.name) {
75+
free(entry->content.action->action.set_alarm.name);
76+
}
77+
break;
78+
case ConversationActionTypeGenericSentence:
79+
free(entry->content.action->action.generic_sentence.sentence);
80+
break;
81+
case ConversationActionTypeSetReminder:
82+
case ConversationActionTypeDeleteReminder:
83+
case ConversationActionTypeUpdateChecklist:
84+
// These have nothing to clean up.
85+
break;
7486
}
7587
free(entry->content.action);
7688
break;

app/src/c/converse/conversation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct {
4040
time_t time;
4141
bool is_timer;
4242
bool deleted;
43+
char* name;
4344
} ConversationActionSetAlarm;
4445

4546
typedef struct {

0 commit comments

Comments
 (0)