diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08dd22c9..f609c8fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,7 +61,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)
file(READ version.txt TACTILITY_VERSION)
- add_compile_definitions(TT_VERSION="$TACTILITY_VERSION")
+ add_compile_definitions(TT_VERSION="${TACTILITY_VERSION}")
else()
message("Building for sim target")
endif()
diff --git a/Data/assets/boot_logo.png b/Data/assets/boot_logo.png
index 0a3c5fc8..2ef10057 100644
Binary files a/Data/assets/boot_logo.png and b/Data/assets/boot_logo.png differ
diff --git a/Data/assets/spinner.png b/Data/assets/spinner.png
new file mode 100644
index 00000000..714847df
Binary files /dev/null and b/Data/assets/spinner.png differ
diff --git a/Data/assets_sources/TactilitySpinner.svg b/Data/assets_sources/TactilitySpinner.svg
new file mode 100644
index 00000000..bd5dc84a
--- /dev/null
+++ b/Data/assets_sources/TactilitySpinner.svg
@@ -0,0 +1,275 @@
+
+
+
+
diff --git a/Data/assets_sources/Tactility.svg b/Data/assets_sources/boot_logo.svg
similarity index 94%
rename from Data/assets_sources/Tactility.svg
rename to Data/assets_sources/boot_logo.svg
index 699ed9cf..1b02be37 100644
--- a/Data/assets_sources/Tactility.svg
+++ b/Data/assets_sources/boot_logo.svg
@@ -2,16 +2,16 @@
@@ -214,7 +214,8 @@
inkscape:label="Large with textt"
inkscape:export-filename="g4.png"
inkscape:export-xdpi="21.879999"
- inkscape:export-ydpi="21.879999">
+ inkscape:export-ydpi="21.879999"
+ transform="matrix(0.23518519,0,0,0.23518519,-14.084653,-11.732801)">
+ d="M 20.022406,150 H 70 v 10 H 10 a 10.011209,10.011209 135.06412 0 1 10.022406,-10 z"
+ transform="matrix(0.98657364,0,0,1,0.13426361,0)" />
+ transform="matrix(-0.98657364,0,0,-1,109.86574,330)" />
(malloc(sizeof(void*) * SCANDIR_LIMIT));
+ if (*output == nullptr) {
+ TT_LOG_E(TAG, "Out of memory");
+ closedir(dir);
+ return -1;
+ }
+
struct dirent** dirent_array = *output;
- int dirent_buffer_index = 0;
+ int next_dirent_index = 0;
struct dirent* current_entry;
+ bool out_of_memory = false;
while ((current_entry = readdir(dir)) != nullptr) {
if (filter(current_entry) == 0) {
- dirent_array[dirent_buffer_index] = static_cast(malloc(sizeof(struct dirent)));
- memcpy(dirent_array[dirent_buffer_index], current_entry, sizeof(struct dirent));
+ dirent_array[next_dirent_index] = static_cast(malloc(sizeof(struct dirent)));
+ if (dirent_array[next_dirent_index] != nullptr) {
+ memcpy(dirent_array[next_dirent_index], current_entry, sizeof(struct dirent));
- dirent_buffer_index++;
- if (dirent_buffer_index >= SCANDIR_LIMIT) {
- TT_LOG_E(TAG, "Directory has more than %d files", SCANDIR_LIMIT);
+ next_dirent_index++;
+ if (next_dirent_index >= SCANDIR_LIMIT) {
+ TT_LOG_E(TAG, "Directory has more than %d files", SCANDIR_LIMIT);
+ break;
+ }
+ } else {
+ TT_LOG_E(TAG, "Alloc failed. Aborting and cleaning up.");
+ out_of_memory = true;
break;
}
}
}
- if (dirent_buffer_index == 0) {
+ // Out-of-memory clean-up
+ if (out_of_memory && next_dirent_index > 0) {
+ for (int i = 0; i < next_dirent_index; ++i) {
+ TT_LOG_I(TAG, "Cleanup item %d", i);
+ free(dirent_array[i]);
+ }
+ TT_LOG_I(TAG, "Free");
+ free(*output);
+ closedir(dir);
+ return -1;
+ // Empty directory
+ } else if (next_dirent_index == 0) {
free(*output);
*output = nullptr;
} else {
if (sort) {
- qsort(dirent_array, dirent_buffer_index, sizeof(struct dirent*), (__compar_fn_t)sort);
+ qsort(dirent_array, next_dirent_index, sizeof(struct dirent*), (__compar_fn_t)sort);
}
}
closedir(dir);
- return dirent_buffer_index;
+ return next_dirent_index;
};
}
diff --git a/Tactility/Source/app/files/Files.cpp b/Tactility/Source/app/files/Files.cpp
index b9a93272..2a16fb06 100644
--- a/Tactility/Source/app/files/Files.cpp
+++ b/Tactility/Source/app/files/Files.cpp
@@ -204,7 +204,7 @@ static void createFileWidget(lv_obj_t* parent, struct dirent* dir_entry) {
static void updateViews(std::shared_ptr data) {
lv_obj_clean(data->list);
for (int i = 0; i < data->dir_entries_count; ++i) {
- TT_LOG_I(TAG, "Entry: %s %d", data->dir_entries[i]->d_name, data->dir_entries[i]->d_type);
+ TT_LOG_D(TAG, "Entry: %s %d", data->dir_entries[i]->d_name, data->dir_entries[i]->d_type);
createFileWidget(data->list, data->dir_entries[i]);
}
}
diff --git a/Tactility/Source/app/wifimanage/View.cpp b/Tactility/Source/app/wifimanage/View.cpp
index ad8eb983..1fd1f0e5 100644
--- a/Tactility/Source/app/wifimanage/View.cpp
+++ b/Tactility/Source/app/wifimanage/View.cpp
@@ -6,6 +6,7 @@
#include "service/wifi/Wifi.h"
#include "lvgl/Style.h"
#include "lvgl/Toolbar.h"
+#include "lvgl/Spinner.h"
#include
#include
@@ -96,10 +97,7 @@ void View::createSsidListItem(const service::wifi::WifiApRecord& record, bool is
lv_obj_align(info_label, LV_ALIGN_CENTER, 0, 0);
if (isConnecting) {
- lv_obj_t* connecting_spinner = lv_spinner_create(wrapper);
- lv_obj_set_size(connecting_spinner, 40, 40);
- lv_spinner_set_anim_params(connecting_spinner, 1000, 60);
- lv_obj_set_style_pad_all(connecting_spinner, 4, 0);
+ lv_obj_t* connecting_spinner = tt_spinner_create(wrapper);
lv_obj_align_to(connecting_spinner, info_wrapper, LV_ALIGN_OUT_LEFT_MID, -8, 0);
} else {
const char* icon = service::statusbar::getWifiStatusIconForRssi(record.rssi, record.auth_mode != WIFI_AUTH_OPEN);
diff --git a/Tactility/Source/lvgl/Spinner.cpp b/Tactility/Source/lvgl/Spinner.cpp
new file mode 100644
index 00000000..23722094
--- /dev/null
+++ b/Tactility/Source/lvgl/Spinner.cpp
@@ -0,0 +1,53 @@
+#define LV_USE_PRIVATE_API 1 // For actual lv_obj_t declaration
+
+#include "lvgl.h"
+#include "CoreDefines.h"
+#include "Log.h"
+
+static void tt_spinner_constructor(const lv_obj_class_t* object_class, lv_obj_t* object);
+
+const lv_obj_class_t tt_spinner_class = {
+ .base_class = &lv_image_class,
+ .constructor_cb = tt_spinner_constructor,
+ .destructor_cb = nullptr,
+ .event_cb = nullptr,
+ .user_data = nullptr,
+ .name = "tt_spinner",
+ .width_def = 0,
+ .height_def = 0,
+ .editable = 0,
+ .group_def = 0,
+ .instance_size = 0,
+ .theme_inheritable = 0
+};
+
+lv_obj_t* tt_spinner_create(lv_obj_t* parent) {
+ lv_obj_t* obj = lv_obj_class_create_obj(&tt_spinner_class, parent);
+ lv_obj_class_init_obj(obj);
+
+ lv_image_set_src(obj, "A:/assets/spinner.png");
+
+ return obj;
+}
+
+static void anim_rotation_callback(void* var, int32_t v) {
+ auto* object = (lv_obj_t*) var;
+ auto width = lv_obj_get_width(object);
+ auto height = lv_obj_get_width(object);
+ lv_obj_set_style_transform_pivot_x(object, width / 2, 0);
+ lv_obj_set_style_transform_pivot_y(object, height / 2, 0);
+ lv_obj_set_style_transform_rotation(object, v, 0);
+}
+
+static void tt_spinner_constructor(TT_UNUSED const lv_obj_class_t* object_class, lv_obj_t* object) {
+ lv_obj_remove_flag(object, LV_OBJ_FLAG_CLICKABLE);
+
+ lv_anim_t a;
+ lv_anim_init(&a);
+ lv_anim_set_var(&a, object);
+ lv_anim_set_values(&a, 0, 3600);
+ lv_anim_set_duration(&a, 800);
+ lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
+ lv_anim_set_exec_cb(&a, anim_rotation_callback);
+ lv_anim_start(&a);
+}
diff --git a/Tactility/Source/lvgl/Spinner.h b/Tactility/Source/lvgl/Spinner.h
new file mode 100644
index 00000000..718005ca
--- /dev/null
+++ b/Tactility/Source/lvgl/Spinner.h
@@ -0,0 +1,8 @@
+#include "lvgl.h"
+
+/**
+ * Create the Tactility spinner widget
+ * @param parent pointer to an object, it will be the parent of the new spinner.
+ * @return the created spinner
+ */
+lv_obj_t* tt_spinner_create(lv_obj_t* parent);
diff --git a/Tactility/Source/lvgl/Toolbar.cpp b/Tactility/Source/lvgl/Toolbar.cpp
index 32eff6b9..77d9c293 100644
--- a/Tactility/Source/lvgl/Toolbar.cpp
+++ b/Tactility/Source/lvgl/Toolbar.cpp
@@ -1,10 +1,10 @@
#define LV_USE_PRIVATE_API 1 // For actual lv_obj_t declaration
#include "Toolbar.h"
-#include "Tactility.h"
#include "service/loader/Loader.h"
#include "lvgl/Spacer.h"
#include "lvgl/Style.h"
+#include "Spinner.h"
#define SPINNER_HEIGHT TOOLBAR_HEIGHT
@@ -90,6 +90,7 @@ lv_obj_t* toolbar_create(lv_obj_t* parent, const std::string& title) {
lv_obj_set_flex_flow(toolbar->action_container, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_all(toolbar->action_container, 0, 0);
lv_obj_set_style_border_width(toolbar->action_container, 0, 0);
+ lv_obj_set_flex_align(toolbar->action_container, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START);
toolbar_set_nav_action(obj, LV_SYMBOL_CLOSE, &stop_app, nullptr);
@@ -137,11 +138,7 @@ lv_obj_t* toolbar_add_switch_action(lv_obj_t* obj) {
lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj) {
auto* toolbar = (Toolbar*)obj;
- lv_obj_t* widget = lv_spinner_create(toolbar->action_container);
- lv_obj_set_size(widget, SPINNER_HEIGHT, SPINNER_HEIGHT);
- lv_spinner_set_anim_params(widget, 1000, 60);
- lv_obj_set_style_pad_all(widget, 4, 0);
- return widget;
+ return tt_spinner_create(toolbar->action_container);
}
} // namespace