Skip to content

Commit 86539c0

Browse files
committed
Add yes/no/retry quick responses to long press menu.
Signed-off-by: Katharine Berry <[email protected]>
1 parent 74c8eab commit 86539c0

File tree

6 files changed

+100
-6
lines changed

6 files changed

+100
-6
lines changed

app/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@ add_executable(tiny_assistant_app
7070
src/c/converse/segments/widgets/timer.c
7171
src/c/converse/segments/widgets/number.c
7272
src/c/menus/feedback_window.c
73-
src/c/appglance/manager.c
7473
src/c/settings/settings.c
7574
src/c/vibes/sad_vibe_score.c
7675
src/c/util/formatted_text_layer.c
7776
src/c/menus/about_window.c
7877
src/c/converse/report_window.c
79-
src/c/vibes/haptic_feedback.c)
78+
src/c/vibes/haptic_feedback.c
79+
src/c/util/action_menu_crimes.c
80+
)

app/src/c/converse/conversation.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,16 @@ ConversationEntry* conversation_peek(Conversation* conversation) {
265265
return &conversation->entries[conversation->entry_count-1];
266266
}
267267

268+
ConversationEntry* conversation_get_last_of_type(Conversation* conversation, EntryType type) {
269+
for (int i = conversation->entry_count - 1; i >= 0; --i) {
270+
ConversationEntry* entry = &conversation->entries[i];
271+
if (entry->type == type) {
272+
return entry;
273+
}
274+
}
275+
return NULL;
276+
}
277+
268278
const char* prv_type_to_string(EntryType type) {
269279
switch(type) {
270280
case EntryTypePrompt:

app/src/c/converse/conversation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ bool conversation_is_idle(Conversation* conversation);
170170
bool conversation_assistant_just_started(Conversation* conversation);
171171
ConversationEntry* conversation_entry_at_index(Conversation* conversation, int index);
172172
ConversationEntry* conversation_peek(Conversation* conversation);
173+
ConversationEntry* conversation_get_last_of_type(Conversation* conversation, EntryType type);
173174
EntryType conversation_entry_get_type(ConversationEntry* entry);
174175

175176
ConversationPrompt* conversation_entry_get_prompt(ConversationEntry* entry);

app/src/c/converse/session_window.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "segments/segment_layer.h"
2222
#include "../util/thinking_layer.h"
2323
#include "../util/style.h"
24+
#include "../util/action_menu_crimes.h"
2425
#include "../vibes/haptic_feedback.h"
2526

2627
#include <pebble.h>
@@ -49,6 +50,7 @@ struct SessionWindow {
4950
AppTimer *timeout_handle;
5051
int timeout;
5152
char* starting_prompt;
53+
char* last_prompt_label;
5254
};
5355

5456
static void prv_window_load(Window *window);
@@ -68,6 +70,7 @@ static void prv_refresh_timeout(SessionWindow* sw);
6870
static void prv_timed_out(void *ctx);
6971
static void prv_cancel_timeout(SessionWindow* sw);
7072
static void prv_action_menu_query(ActionMenu *action_menu, const ActionMenuItem *action, void *context);
73+
static void prv_action_menu_input(ActionMenu *action_menu, const ActionMenuItem *action, void *context);
7174
static void prv_action_menu_report_thread(ActionMenu *action_menu, const ActionMenuItem *action, void *context);
7275

7376
void session_window_push(int timeout, char *starting_prompt) {
@@ -373,28 +376,51 @@ static void prv_select_clicked(ClickRecognizerRef recognizer, void *context) {
373376
}
374377

375378
static void prv_destroy_action_menu(ActionMenu *action_menu, const ActionMenuItem *item, void *context) {
379+
SessionWindow *sw = context;
376380
action_menu_hierarchy_destroy(action_menu_get_root_level(action_menu), NULL, NULL);
381+
if (sw->last_prompt_label) {
382+
free(sw->last_prompt_label);
383+
sw->last_prompt_label = NULL;
384+
}
377385
}
378386

379387
static void prv_select_long_pressed(ClickRecognizerRef recognizer, void *context) {
380388
SessionWindow* sw = context;
381389
if (!conversation_is_idle(conversation_manager_get_conversation(sw->manager))) {
382390
return;
383391
}
384-
ActionMenuLevel *action_menu = action_menu_level_create(2);
385-
action_menu_level_add_action(action_menu, "Prompt", prv_action_menu_query, sw);
386-
action_menu_level_add_action(action_menu, "Report conversation", prv_action_menu_report_thread, sw);
392+
ActionMenuLevel *action_menu = action_menu_level_create(5);
393+
action_menu_level_add_action(action_menu, "\"Yes.\"", prv_action_menu_input, "Yes.");
394+
action_menu_level_add_action(action_menu, "\"No.\"", prv_action_menu_input, "No.");
395+
Conversation *conversation = conversation_manager_get_conversation(sw->manager);
396+
ConversationEntry *entry = conversation_peek(conversation);
397+
EntryType type = conversation_entry_get_type(entry);
398+
int separator_index = 3;
399+
if (type == EntryTypeError) {
400+
ConversationEntry *last_prompt = conversation_get_last_of_type(conversation, EntryTypePrompt);
401+
if (last_prompt != NULL) {
402+
ConversationPrompt *prompt = conversation_entry_get_prompt(last_prompt);
403+
sw->last_prompt_label = malloc(strlen(prompt->prompt) + 3);
404+
snprintf(sw->last_prompt_label, strlen(prompt->prompt) + 3, "\"%s\"", prompt->prompt);
405+
action_menu_level_add_action(action_menu, sw->last_prompt_label, prv_action_menu_input, prompt->prompt);
406+
separator_index++;
407+
}
408+
}
409+
action_menu_level_add_action(action_menu, "Dictate", prv_action_menu_query, NULL);
410+
action_menu_level_set_separator_index(action_menu, separator_index);
411+
action_menu_level_add_action(action_menu, "Report conversation", prv_action_menu_report_thread, NULL);
387412
ActionMenuConfig config = (ActionMenuConfig) {
388413
.root_level = action_menu,
389414
.colors = {
390415
.background = BRANDED_BACKGROUND_COLOUR,
391416
.foreground = gcolor_legible_over(BRANDED_BACKGROUND_COLOUR),
392417
},
393-
.align = ActionMenuAlignCenter,
418+
.align = ActionMenuAlignTop,
394419
.context = sw,
395420
.did_close = prv_destroy_action_menu,
396421
};
397422
vibe_haptic_feedback();
423+
sw->query_time = time(NULL);
398424
action_menu_open(&config);
399425
}
400426

@@ -403,6 +429,14 @@ static void prv_action_menu_query(ActionMenu *action_menu, const ActionMenuItem
403429
dictation_session_start(sw->dictation);
404430
}
405431

432+
433+
static void prv_action_menu_input(ActionMenu *action_menu, const ActionMenuItem *action, void *context) {
434+
SessionWindow* sw = context;
435+
const char* input = action_menu_item_get_action_data(action);
436+
conversation_manager_add_input(sw->manager, input);
437+
sw->query_time = time(NULL);
438+
}
439+
406440
static void prv_action_menu_report_thread(ActionMenu *action_menu, const ActionMenuItem *action, void *context) {
407441
SessionWindow* sw = context;
408442
report_window_push(conversation_get_thread_id(conversation_manager_get_conversation(sw->manager)));
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "action_menu_crimes.h"
18+
#include <pebble.h>
19+
20+
typedef struct {
21+
char padding[12];
22+
unsigned separator_index;
23+
} ActionMenuLevelHack;
24+
25+
void action_menu_level_set_separator_index(ActionMenuLevel *level, unsigned index) {
26+
ActionMenuLevelHack *hack = (ActionMenuLevelHack *)level;
27+
hack->separator_index = index;
28+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <pebble.h>
20+
void action_menu_level_set_separator_index(ActionMenuLevel *level, unsigned index);

0 commit comments

Comments
 (0)