Просмотр исходного кода

upd totp

with fixes by Willy-JL
MX 9 месяцев назад
Родитель
Сommit
2b582757a6

+ 1 - 1
application.fam

@@ -7,7 +7,7 @@ App(
     requires=["gui", "cli", "dialogs", "storage", "input", "notification", "bt"],
     stack_size=2 * 1024,
     order=20,
-    fap_version="5.170",
+    fap_version="5.171",
     fap_author="Alexander Kopachov (@akopachov)",
     fap_description="Software-based TOTP/HOTP authenticator for Flipper Zero device",
     fap_weburl="https://github.com/akopachov/flipper-zero_authenticator",

+ 4 - 4
cli/cli.c

@@ -37,7 +37,7 @@ static void run_external_cli_plugin_handler(
     const char* handler_name,
     TotpCliContext* cli_context,
     FuriString* args,
-    Cli* cli) {
+    PipeSide* pipe) {
     Storage* storage = furi_record_open(RECORD_STORAGE);
     FlipperApplication* plugin_app = flipper_application_alloc(
         storage, composite_api_resolver_get(cli_context->plugin_api_resolver));
@@ -81,14 +81,14 @@ static void run_external_cli_plugin_handler(
 
         const CliPlugin* plugin = app_descriptor->entry_point;
 
-        plugin->handle(cli_context->plugin_state, args, cli);
+        plugin->handle(cli_context->plugin_state, args, pipe);
     } while(false);
     flipper_application_free(plugin_app);
 
     furi_record_close(RECORD_STORAGE);
 }
 
-static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
+static void totp_cli_handler(PipeSide* pipe, FuriString* args, void* context) {
     TotpCliContext* cli_context = context;
 
     FuriString* cmd = furi_string_alloc();
@@ -145,7 +145,7 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
     }
 
     if(external_plugin_name != NULL) {
-        run_external_cli_plugin_handler(external_plugin_name, cli_context, args, cli);
+        run_external_cli_plugin_handler(external_plugin_name, cli_context, args, pipe);
     }
 
     furi_string_free(cmd);

+ 1 - 1
cli/cli_plugin_interface.h

@@ -10,5 +10,5 @@
 
 typedef struct {
     const char* name;
-    void (*handle)(PluginState*, FuriString*, Cli*);
+    void (*handle)(PluginState*, FuriString*, PipeSide*);
 } CliPlugin;

+ 8 - 8
cli/cli_shared_methods.c

@@ -5,13 +5,13 @@
 #include "cli_helpers.h"
 #include "../types/plugin_event.h"
 
-bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) {
+bool totp_cli_ensure_authenticated(const PluginState* plugin_state, PipeSide* pipe) {
     if(plugin_state->current_scene == TotpSceneAuthentication) {
         TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n");
 
         while((plugin_state->current_scene == TotpSceneAuthentication ||
                plugin_state->current_scene == TotpSceneNone) &&
-              !cli_cmd_interrupt_received(cli)) {
+              !cli_is_pipe_broken_or_is_etx_next_char(pipe)) {
             furi_delay_ms(100);
         }
 
@@ -33,17 +33,17 @@ void totp_cli_force_close_app(void* ctx) {
     furi_message_queue_put(event_queue, &event, FuriWaitForever);
 }
 
-bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input) {
+bool totp_cli_read_line(PipeSide* pipe, FuriString* out_str, bool mask_user_input) {
     uint8_t c;
-    while(cli_read(cli, &c, 1) == 1) {
+    while(pipe_receive(pipe, &c, 1) == 1) {
         if(c == CliKeyEsc) {
             // Some keys generating escape-sequences
             // We need to ignore them as we care about alpha-numerics only
             uint8_t c2;
-            cli_read_timeout(cli, &c2, 1, 0);
-            cli_read_timeout(cli, &c2, 1, 0);
+            pipe_receive(pipe, &c2, 1);
+            pipe_receive(pipe, &c2, 1);
         } else if(c == CliKeyETX) {
-            cli_nl(cli);
+            printf("\r\n");
             return false;
         } else if(
             (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
@@ -62,7 +62,7 @@ bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input) {
                 furi_string_left(out_str, out_str_size - 1);
             }
         } else if(c == CliKeyCR) {
-            cli_nl(cli);
+            printf("\r\n");
             break;
         }
     }

+ 4 - 4
cli/cli_shared_methods.h

@@ -12,10 +12,10 @@ extern "C" {
  * @brief Checks whether user is authenticated and entered correct PIN.
  *        If user is not authenticated it prompts user to enter correct PIN to authenticate.
  * @param plugin_state application state
- * @param cli pointer to the firmware CLI subsystem 
+ * @param pipe pointer to the CLI pipe
  * @return \c true if user is already authenticated or successfully authenticated; \c false otherwise
  */
-bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli);
+bool totp_cli_ensure_authenticated(const PluginState* plugin_state, PipeSide* pipe);
 
 /**
  * @brief Forces application to be instantly closed
@@ -25,12 +25,12 @@ void totp_cli_force_close_app(void* ctx);
 
 /**
  * @brief Reads line of characters from console
- * @param cli pointer to the firmware CLI subsystem 
+ * @param pipe pointer to the CLI pipe
  * @param out_str pointer to an output string to put read line to
  * @param mask_user_input whether to mask input characters in console or not
  * @return \c true if line successfully read and confirmed; \c false otherwise
  */
-bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input);
+bool totp_cli_read_line(PipeSide* pipe, FuriString* out_str, bool mask_user_input);
 
 /**
  * @brief Extracts \c uint8_t value and trims arguments string

+ 4 - 4
cli/plugins/automation/automation.c

@@ -54,8 +54,8 @@ static void print_initial_delay(uint16_t initial_delay, const char* color) {
     TOTP_CLI_PRINTF_COLORFUL(color, "%.1f", delay_sec);
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -131,7 +131,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
                 print_initial_delay(
                     plugin_state->automation_initial_delay, TOTP_CLI_COLOR_SUCCESS);
                 TOTP_CLI_PRINTF_SUCCESS(" sec.]");
-                cli_nl(cli);
+                printf("\r\n");
             } else {
                 TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
             }
@@ -154,7 +154,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
             TOTP_CLI_PRINTF_INFO(" [");
             print_initial_delay(plugin_state->automation_initial_delay, TOTP_CLI_COLOR_INFO);
             TOTP_CLI_PRINTF_INFO(" sec.]");
-            cli_nl(cli);
+            printf("\r\n");
         }
     } while(false);
 

+ 4 - 4
cli/plugins/delete/delete.c

@@ -8,8 +8,8 @@
 
 #define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX "-f"
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -55,7 +55,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
         fflush(stdout);
         char user_pick;
         do {
-            user_pick = tolower(cli_getc(cli));
+            user_pick = tolower(getchar());
         } while(user_pick != 'y' && user_pick != 'n' && user_pick != CliKeyCR &&
                 user_pick != CliKeyETX && user_pick != CliKeyEsc);
 
@@ -92,4 +92,4 @@ static const FlipperAppPluginDescriptor plugin_descriptor = {
 
 const FlipperAppPluginDescriptor* totp_cli_delete_plugin_ep() {
     return &plugin_descriptor;
-}
+}

+ 2 - 2
cli/plugins/details/details.c

@@ -76,8 +76,8 @@ static void print_automation_features(
     }
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 

+ 5 - 5
cli/plugins/export/export.c

@@ -49,10 +49,10 @@ static void print_uri_component(const char* data, size_t length) {
     }
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
     UNUSED(args);
     UNUSED(plugin_state);
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -78,7 +78,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
         return;
     }
 
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -90,7 +90,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
 
     size_t original_index = totp_token_info_iterator_get_current_token_index(iterator_context);
 
-    cli_nl(cli);
+    printf("\r\n");
     TOTP_CLI_PRINTF("# --- EXPORT LIST BEGIN ---\r\n");
 
     for(size_t i = 0; i < total_count; i++) {
@@ -116,7 +116,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
         } else {
             TOTP_CLI_PRINTF("&period=%" PRIu8, token_info->duration);
         }
-        cli_nl(cli);
+        printf("\r\n");
     }
 
     TOTP_CLI_PRINTF("# --- EXPORT LIST END ---\r\n\r\n");

+ 3 - 3
cli/plugins/help/help.c

@@ -5,9 +5,9 @@
 #include "../../cli_helpers.h"
 #include "../../cli_plugin_interface.h"
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
     UNUSED(args);
-    UNUSED(cli);
+    UNUSED(pipe);
     UNUSED(plugin_state);
 
     Storage* storage = furi_record_open(RECORD_STORAGE);
@@ -19,7 +19,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
         uint8_t buffer[32U];
         size_t bytes_read;
         while((bytes_read = stream_read(stream, &buffer[0], sizeof(buffer))) > 0) {
-            cli_write(cli, &buffer[0], bytes_read);
+            pipe_send(pipe, &buffer[0], bytes_read);
         }
     }
 

+ 2 - 2
cli/plugins/list/list.c

@@ -30,8 +30,8 @@ static const TotpCliListFormatter available_formatters[] = {
      .body_item_formatter = &list_output_formatter_print_body_item_tsv,
      .footer_formatter = &list_output_formatter_print_footer_tsv}};
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 

+ 5 - 5
cli/plugins/modify/add/add.c

@@ -11,7 +11,7 @@
 
 struct TotpAddContext {
     FuriString* args;
-    Cli* cli;
+    PipeSide* pipe;
     const CryptoSettings* crypto_settings;
 };
 
@@ -58,7 +58,7 @@ static TotpIteratorUpdateTokenResult
     // Reading token secret
     furi_string_reset(temp_str);
     TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]:\r\n");
-    if(!totp_cli_read_line(context_t->cli, temp_str, mask_user_input)) {
+    if(!totp_cli_read_line(context_t->pipe, temp_str, mask_user_input)) {
         TOTP_CLI_DELETE_LAST_LINE();
         furi_string_secure_free(temp_str);
         return TotpIteratorUpdateTokenResultCancelled;
@@ -82,8 +82,8 @@ static TotpIteratorUpdateTokenResult
     return TotpIteratorUpdateTokenResultSuccess;
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -93,7 +93,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
     TOTP_CLI_LOCK_UI(plugin_state);
 
     struct TotpAddContext add_context = {
-        .args = args, .cli = cli, .crypto_settings = &plugin_state->crypto_settings};
+        .args = args, .pipe = pipe, .crypto_settings = &plugin_state->crypto_settings};
     TotpIteratorUpdateTokenResult add_result =
         totp_token_info_iterator_add_new_token(iterator_context, &add_token_handler, &add_context);
 

+ 5 - 5
cli/plugins/modify/update/update.c

@@ -13,7 +13,7 @@
 
 struct TotpUpdateContext {
     FuriString* args;
-    Cli* cli;
+    PipeSide* pipe;
     const CryptoSettings* crypto_settings;
 };
 
@@ -87,7 +87,7 @@ static TotpIteratorUpdateTokenResult
         // Reading token secret
         furi_string_reset(temp_str);
         TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]:\r\n");
-        bool token_secret_read = totp_cli_read_line(context_t->cli, temp_str, mask_user_input);
+        bool token_secret_read = totp_cli_read_line(context_t->pipe, temp_str, mask_user_input);
         TOTP_CLI_DELETE_LAST_LINE();
         if(!token_secret_read) {
             furi_string_secure_free(temp_str);
@@ -110,8 +110,8 @@ static TotpIteratorUpdateTokenResult
     return TotpIteratorUpdateTokenResultSuccess;
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -131,7 +131,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
     totp_token_info_iterator_go_to(iterator_context, token_number - 1);
 
     struct TotpUpdateContext update_context = {
-        .args = args, .cli = cli, .crypto_settings = &plugin_state->crypto_settings};
+        .args = args, .pipe = pipe, .crypto_settings = &plugin_state->crypto_settings};
     TotpIteratorUpdateTokenResult update_result = totp_token_info_iterator_update_current_token(
         iterator_context, &update_token_handler, &update_context);
 

+ 2 - 2
cli/plugins/move/move.c

@@ -7,8 +7,8 @@
 #include "../../../services/config/config.h"
 #include "../../../ui/scene_director.h"
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 

+ 4 - 4
cli/plugins/notification/notification.c

@@ -29,8 +29,8 @@ static void
     }
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 
@@ -67,7 +67,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
             if(totp_config_file_update_notification_method(plugin_state)) {
                 TOTP_CLI_PRINTF_SUCCESS("Notification method is set to ");
                 totp_cli_command_notification_print_method(new_method, TOTP_CLI_COLOR_SUCCESS);
-                cli_nl(cli);
+                printf("\r\n");
             } else {
                 TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
             }
@@ -77,7 +77,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
             TOTP_CLI_PRINTF_INFO("Current notification method is ");
             totp_cli_command_notification_print_method(
                 plugin_state->notification_method, TOTP_CLI_COLOR_INFO);
-            cli_nl(cli);
+            printf("\r\n");
         }
     } while(false);
 

+ 7 - 8
cli/plugins/pin/pin.c

@@ -36,17 +36,16 @@ static inline uint8_t totp_cli_key_to_pin_code(uint8_t key) {
     return code;
 }
 
-static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) {
+static bool totp_cli_read_pin(PipeSide* pipe, uint8_t* pin, uint8_t* pin_length) {
     TOTP_CLI_PRINTF("Enter new PIN (use arrow keys on your keyboard): ");
     fflush(stdout);
     uint8_t c;
     *pin_length = 0;
-    while(cli_read(cli, &c, 1) == 1) {
+    while(pipe_receive(pipe, &c, 1) == 1) {
         if(c == CliKeyEsc) {
             uint8_t c2;
             uint8_t c3;
-            if(cli_read_timeout(cli, &c2, 1, 0) == 1 && cli_read_timeout(cli, &c3, 1, 0) == 1 &&
-               c2 == 0x5b) {
+            if(pipe_receive(pipe, &c2, 1) == 1 && pipe_receive(pipe, &c3, 1) == 1 && c2 == 0x5b) {
                 uint8_t code = totp_cli_key_to_pin_code(c3);
                 if(code > 0) {
                     pin[*pin_length] = code;
@@ -66,7 +65,7 @@ static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) {
                 TOTP_CLI_DELETE_LAST_CHAR();
             }
         } else if(c == CliKeyCR) {
-            cli_nl(cli);
+            printf("\r\n");
             break;
         }
     }
@@ -75,7 +74,7 @@ static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) {
     return true;
 }
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
     UNUSED(plugin_state);
     FuriString* temp_str = furi_string_alloc();
 
@@ -110,14 +109,14 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
         arguments_parsed = false;
     }
 
-    if(arguments_parsed && totp_cli_ensure_authenticated(plugin_state, cli)) {
+    if(arguments_parsed && totp_cli_ensure_authenticated(plugin_state, pipe)) {
         TOTP_CLI_LOCK_UI(plugin_state);
         do {
             uint8_t new_pin[CRYPTO_IV_LENGTH];
             memset(&new_pin[0], 0, CRYPTO_IV_LENGTH);
             uint8_t new_pin_length = 0;
             if(do_change) {
-                if(!totp_cli_read_pin(cli, &new_pin[0], &new_pin_length)) {
+                if(!totp_cli_read_pin(pipe, &new_pin[0], &new_pin_length)) {
                     memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
                     break;
                 }

+ 2 - 2
cli/plugins/reset/reset.c

@@ -7,7 +7,7 @@
 
 #define TOTP_CLI_RESET_CONFIRMATION_KEYWORD "YES"
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
     UNUSED(args);
     TOTP_CLI_LOCK_UI(plugin_state);
     TOTP_CLI_PRINTF_WARNING(
@@ -16,7 +16,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
     TOTP_CLI_PRINTF_WARNING("Type \"" TOTP_CLI_RESET_CONFIRMATION_KEYWORD
                             "\" and hit <ENTER> to confirm:\r\n");
     FuriString* temp_str = furi_string_alloc();
-    bool is_confirmed = totp_cli_read_line(cli, temp_str, false) &&
+    bool is_confirmed = totp_cli_read_line(pipe, temp_str, false) &&
                         furi_string_cmpi_str(temp_str, TOTP_CLI_RESET_CONFIRMATION_KEYWORD) == 0;
     furi_string_free(temp_str);
     if(is_confirmed) {

+ 2 - 2
cli/plugins/timezone/timezone.c

@@ -6,10 +6,10 @@
 #include "../../cli_plugin_interface.h"
 #include "../../cli_shared_methods.h"
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
     UNUSED(args);
     UNUSED(plugin_state);
-    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+    if(!totp_cli_ensure_authenticated(plugin_state, pipe)) {
         return;
     }
 

+ 8 - 4
cli/plugins/version/version.c

@@ -3,12 +3,16 @@
 #include "../../cli_plugin_interface.h"
 #include "../../../version.h"
 
-static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
     UNUSED(args);
-    UNUSED(cli);
+    UNUSED(pipe);
     UNUSED(plugin_state);
     TOTP_CLI_PRINTF(
-        "%" PRIu8 ".%" PRIu8 ".%" PRIu8 "\r\n",
+        "%" PRIu8 ".%" PRIu8 ".%" PRIu8
+#ifdef TOTP_APP_VERSION_META
+        "+" TOTP_APP_VERSION_META
+#endif
+        "\r\n",
         TOTP_APP_VERSION_MAJOR,
         TOTP_APP_VERSION_MINOR,
         TOTP_APP_VERSION_PATCH);
@@ -24,4 +28,4 @@ static const FlipperAppPluginDescriptor plugin_descriptor = {
 
 const FlipperAppPluginDescriptor* totp_cli_version_plugin_ep() {
     return &plugin_descriptor;
-}
+}

+ 2 - 1
ui/scenes/generate_token/totp_scene_generate_token.c

@@ -427,13 +427,14 @@ bool totp_scene_generate_token_handle_event(
             break;
         }
         case InputKeyOk:
-            totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu);
             break;
         case InputKeyBack:
             break;
         default:
             break;
         }
+    } else if(event->input.type == InputTypeShort && event->input.key == InputKeyOk) {
+        totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu);
     }
 
     return true;

+ 1 - 1
version.h

@@ -2,4 +2,4 @@
 
 #define TOTP_APP_VERSION_MAJOR (5)
 #define TOTP_APP_VERSION_MINOR (17)
-#define TOTP_APP_VERSION_PATCH (0)
+#define TOTP_APP_VERSION_PATCH (1)