From 5632d74db6329f0bc462e00a99d1c247413e6dfd Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Sun, 10 Nov 2024 15:20:35 +0100 Subject: [PATCH] Added text viewer app (#74) --- tactility/src/apps/system/files/files.c | 21 +++++++ .../apps/system/image_viewer/image_viewer.c | 2 +- .../src/apps/system/text_viewer/text_viewer.c | 40 ++++++++++++ .../src/apps/system/text_viewer/text_viewer.h | 11 ++++ tactility/src/tactility.c | 2 + tactility/src/ui/label_utils.c | 62 +++++++++++++++++++ tactility/src/ui/label_utils.h | 13 ++++ 7 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 tactility/src/apps/system/text_viewer/text_viewer.c create mode 100644 tactility/src/apps/system/text_viewer/text_viewer.h create mode 100644 tactility/src/ui/label_utils.c create mode 100644 tactility/src/ui/label_utils.h diff --git a/tactility/src/apps/system/files/files.c b/tactility/src/apps/system/files/files.c index b269352c..1dcdf8d8 100644 --- a/tactility/src/apps/system/files/files.c +++ b/tactility/src/apps/system/files/files.c @@ -2,6 +2,7 @@ #include "app.h" #include "apps/system/image_viewer/image_viewer.h" +#include "apps/system/text_viewer/text_viewer.h" #include "assets.h" #include "check.h" #include "file_utils.h" @@ -41,6 +42,17 @@ static bool is_supported_image_file(const char* filename) { return has_file_extension(filename, ".png"); } +static bool is_supported_text_file(const char* filename) { + return has_file_extension(filename, ".txt") || + has_file_extension(filename, ".ini") || + has_file_extension(filename, ".json") || + has_file_extension(filename, ".yaml") || + has_file_extension(filename, ".yml") || + has_file_extension(filename, ".lua") || + has_file_extension(filename, ".js") || + has_file_extension(filename, ".properties"); +} + // region Views static void update_views(FilesData* data); @@ -92,6 +104,15 @@ static void view_file(const char* path, const char* filename) { Bundle bundle = tt_bundle_alloc(); tt_bundle_put_string(bundle, IMAGE_VIEWER_FILE_ARGUMENT, processed_filepath); loader_start_app("image_viewer", false, bundle); + } else if (is_supported_text_file(filename)) { + Bundle bundle = tt_bundle_alloc(); + if (tt_get_platform() == PlatformEsp) { + tt_bundle_put_string(bundle, TEXT_VIEWER_FILE_ARGUMENT, processed_filepath); + } else { + // Remove forward slash, because we need a relative path + tt_bundle_put_string(bundle, TEXT_VIEWER_FILE_ARGUMENT, processed_filepath + 1); + } + loader_start_app("text_viewer", false, bundle); } else { TT_LOG_W(TAG, "opening files of this type is not supported"); } diff --git a/tactility/src/apps/system/image_viewer/image_viewer.c b/tactility/src/apps/system/image_viewer/image_viewer.c index 8ece8b58..ee883988 100644 --- a/tactility/src/apps/system/image_viewer/image_viewer.c +++ b/tactility/src/apps/system/image_viewer/image_viewer.c @@ -36,7 +36,7 @@ const AppManifest image_viewer_app = { .id = "image_viewer", .name = "Image Viewer", .icon = NULL, - .type = AppTypeDesktop, + .type = AppTypeHidden, .on_start = NULL, .on_stop = NULL, .on_show = &app_show, diff --git a/tactility/src/apps/system/text_viewer/text_viewer.c b/tactility/src/apps/system/text_viewer/text_viewer.c new file mode 100644 index 00000000..4d900eea --- /dev/null +++ b/tactility/src/apps/system/text_viewer/text_viewer.c @@ -0,0 +1,40 @@ +#include "text_viewer.h" +#include "log.h" +#include "lvgl.h" +#include "ui/label_utils.h" +#include "ui/style.h" +#include "ui/toolbar.h" + +#define TAG "text_viewer" + +static void app_show(App app, lv_obj_t* parent) { + lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); + tt_toolbar_create_for_app(parent, app); + + lv_obj_t* wrapper = lv_obj_create(parent); + lv_obj_set_width(wrapper, LV_PCT(100)); + lv_obj_set_flex_grow(wrapper, 1); + lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN); + tt_lv_obj_set_style_no_padding(wrapper); + tt_lv_obj_set_style_bg_invisible(wrapper); + + lv_obj_t* text = lv_label_create(wrapper); + lv_obj_align(text, LV_ALIGN_CENTER, 0, 0); + Bundle bundle = tt_app_get_parameters(app); + if (tt_bundle_has_string(bundle, TEXT_VIEWER_FILE_ARGUMENT)) { + const char* filepath = tt_bundle_get_string(bundle, TEXT_VIEWER_FILE_ARGUMENT); + TT_LOG_I(TAG, "Opening %s", filepath); + tt_lv_label_set_text_file(text, filepath); + } +} + +const AppManifest text_viewer_app = { + .id = "text_viewer", + .name = "Text Viewer", + .icon = NULL, + .type = AppTypeHidden, + .on_start = NULL, + .on_stop = NULL, + .on_show = &app_show, + .on_hide = NULL +}; diff --git a/tactility/src/apps/system/text_viewer/text_viewer.h b/tactility/src/apps/system/text_viewer/text_viewer.h new file mode 100644 index 00000000..926f7407 --- /dev/null +++ b/tactility/src/apps/system/text_viewer/text_viewer.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define TEXT_VIEWER_FILE_ARGUMENT "file" + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/tactility/src/tactility.c b/tactility/src/tactility.c index 942aac88..66355eac 100644 --- a/tactility/src/tactility.c +++ b/tactility/src/tactility.c @@ -39,6 +39,7 @@ extern const AppManifest image_viewer_app; extern const AppManifest power_app; extern const AppManifest settings_app; extern const AppManifest system_info_app; +extern const AppManifest text_viewer_app; extern const AppManifest wifi_connect_app; extern const AppManifest wifi_manage_app; @@ -55,6 +56,7 @@ static const AppManifest* const system_apps[] = { &image_viewer_app, &settings_app, &system_info_app, + &text_viewer_app, &wifi_connect_app, &wifi_manage_app, #ifdef ESP_PLATFORM diff --git a/tactility/src/ui/label_utils.c b/tactility/src/ui/label_utils.c new file mode 100644 index 00000000..ca44d90e --- /dev/null +++ b/tactility/src/ui/label_utils.c @@ -0,0 +1,62 @@ +#include "label_utils.h" +#include +#include + +#define TAG "tt_lv_label" + +static long file_get_size(FILE* file) { + long original_offset = ftell(file); + + if (fseek(file, 0, SEEK_END) != 0) { + TT_LOG_E(TAG, "fseek failed"); + return -1; + } + + long file_size = ftell(file); + if (file_size == -1) { + TT_LOG_E(TAG, "Could not get file length"); + return -1; + } + + if (fseek(file, original_offset, SEEK_SET) != 0) { + TT_LOG_E(TAG, "fseek Failed"); + return -1; + } + + return file_size; +} + +static char* str_alloc_from_file(const char* filepath) { + FILE* file = fopen(filepath, "rb"); + + if (file == NULL) { + TT_LOG_E(TAG, "Failed to open %s", filepath); + return NULL; + } + + long content_length = file_get_size(file); + + char* text_buffer = malloc(content_length + 1); + if (text_buffer == NULL) { + TT_LOG_E(TAG, "Insufficient memory. Failed to allocate %ldl bytes.", content_length); + return NULL; + } + + int buffer; + uint32_t buffer_offset = 0; + text_buffer[0] = 0; + while ((buffer = fgetc(file)) != EOF && buffer_offset < content_length) { + text_buffer[buffer_offset] = (char)buffer; + buffer_offset++; + } + text_buffer[buffer_offset] = 0; + + fclose(file); + return text_buffer; +} + +void tt_lv_label_set_text_file(lv_obj_t* label, const char* filepath) { + char* text = str_alloc_from_file(filepath); + lv_label_set_text(label, text); + free(text); +} diff --git a/tactility/src/ui/label_utils.h b/tactility/src/ui/label_utils.h new file mode 100644 index 00000000..7627e5ef --- /dev/null +++ b/tactility/src/ui/label_utils.h @@ -0,0 +1,13 @@ +#pragma once + +#include "lvgl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void tt_lv_label_set_text_file(lv_obj_t* label, const char* filepath); + +#ifdef __cplusplus +} +#endif \ No newline at end of file